]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
disabled WIN64 error, perhaps we should use the name freetype6_x64.dll
[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.integer >= 100)
421                         Con_Printf("%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.integer >= 100)
428                         Con_Printf(" : %f ", alpha);
429                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
430                 if(developer.integer >= 100)
431                         Con_Printf(" = %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                 if (developer.integer)
3575                         Con_Printf("^5GLSL shader %s compiled.\n", permutationname);
3576         }
3577         else
3578                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3579
3580         // free the strings
3581         if (vertexstring)
3582                 Mem_Free(vertexstring);
3583         if (geometrystring)
3584                 Mem_Free(geometrystring);
3585         if (fragmentstring)
3586                 Mem_Free(fragmentstring);
3587 }
3588
3589 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3590 {
3591         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3592         if (r_glsl_permutation != perm)
3593         {
3594                 r_glsl_permutation = perm;
3595                 if (!r_glsl_permutation->program)
3596                 {
3597                         if (!r_glsl_permutation->compiled)
3598                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3599                         if (!r_glsl_permutation->program)
3600                         {
3601                                 // remove features until we find a valid permutation
3602                                 int i;
3603                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3604                                 {
3605                                         // reduce i more quickly whenever it would not remove any bits
3606                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3607                                         if (!(permutation & j))
3608                                                 continue;
3609                                         permutation -= j;
3610                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3611                                         if (!r_glsl_permutation->compiled)
3612                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3613                                         if (r_glsl_permutation->program)
3614                                                 break;
3615                                 }
3616                                 if (i >= SHADERPERMUTATION_COUNT)
3617                                 {
3618                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3619                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3620                                         qglUseProgramObjectARB(0);CHECKGLERROR
3621                                         return; // no bit left to clear, entire mode is broken
3622                                 }
3623                         }
3624                 }
3625                 CHECKGLERROR
3626                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3627         }
3628         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3629 }
3630
3631 #ifdef SUPPORTCG
3632 #include <Cg/cgGL.h>
3633 struct r_cg_permutation_s;
3634 typedef struct r_cg_permutation_s
3635 {
3636         /// hash lookup data
3637         struct r_cg_permutation_s *hashnext;
3638         unsigned int mode;
3639         unsigned int permutation;
3640
3641         /// indicates if we have tried compiling this permutation already
3642         qboolean compiled;
3643         /// 0 if compilation failed
3644         CGprogram vprogram;
3645         CGprogram fprogram;
3646         /// locations of detected parameters in programs, or NULL if not found
3647         CGparameter vp_EyePosition;
3648         CGparameter vp_FogPlane;
3649         CGparameter vp_LightDir;
3650         CGparameter vp_LightPosition;
3651         CGparameter vp_ModelToLight;
3652         CGparameter vp_TexMatrix;
3653         CGparameter vp_BackgroundTexMatrix;
3654         CGparameter vp_ModelViewProjectionMatrix;
3655         CGparameter vp_ModelViewMatrix;
3656
3657         CGparameter fp_Texture_First;
3658         CGparameter fp_Texture_Second;
3659         CGparameter fp_Texture_GammaRamps;
3660         CGparameter fp_Texture_Normal;
3661         CGparameter fp_Texture_Color;
3662         CGparameter fp_Texture_Gloss;
3663         CGparameter fp_Texture_Glow;
3664         CGparameter fp_Texture_SecondaryNormal;
3665         CGparameter fp_Texture_SecondaryColor;
3666         CGparameter fp_Texture_SecondaryGloss;
3667         CGparameter fp_Texture_SecondaryGlow;
3668         CGparameter fp_Texture_Pants;
3669         CGparameter fp_Texture_Shirt;
3670         CGparameter fp_Texture_FogMask;
3671         CGparameter fp_Texture_Lightmap;
3672         CGparameter fp_Texture_Deluxemap;
3673         CGparameter fp_Texture_Attenuation;
3674         CGparameter fp_Texture_Cube;
3675         CGparameter fp_Texture_Refraction;
3676         CGparameter fp_Texture_Reflection;
3677         CGparameter fp_Texture_ShadowMapRect;
3678         CGparameter fp_Texture_ShadowMapCube;
3679         CGparameter fp_Texture_ShadowMap2D;
3680         CGparameter fp_Texture_CubeProjection;
3681         CGparameter fp_Texture_ScreenDepth;
3682         CGparameter fp_Texture_ScreenNormalMap;
3683         CGparameter fp_Texture_ScreenDiffuse;
3684         CGparameter fp_Texture_ScreenSpecular;
3685         CGparameter fp_Alpha;
3686         CGparameter fp_BloomBlur_Parameters;
3687         CGparameter fp_ClientTime;
3688         CGparameter fp_Color_Ambient;
3689         CGparameter fp_Color_Diffuse;
3690         CGparameter fp_Color_Specular;
3691         CGparameter fp_Color_Glow;
3692         CGparameter fp_Color_Pants;
3693         CGparameter fp_Color_Shirt;
3694         CGparameter fp_DeferredColor_Ambient;
3695         CGparameter fp_DeferredColor_Diffuse;
3696         CGparameter fp_DeferredColor_Specular;
3697         CGparameter fp_DeferredMod_Diffuse;
3698         CGparameter fp_DeferredMod_Specular;
3699         CGparameter fp_DistortScaleRefractReflect;
3700         CGparameter fp_EyePosition;
3701         CGparameter fp_FogColor;
3702         CGparameter fp_FogHeightFade;
3703         CGparameter fp_FogPlane;
3704         CGparameter fp_FogPlaneViewDist;
3705         CGparameter fp_FogRangeRecip;
3706         CGparameter fp_LightColor;
3707         CGparameter fp_LightDir;
3708         CGparameter fp_LightPosition;
3709         CGparameter fp_OffsetMapping_Scale;
3710         CGparameter fp_PixelSize;
3711         CGparameter fp_ReflectColor;
3712         CGparameter fp_ReflectFactor;
3713         CGparameter fp_ReflectOffset;
3714         CGparameter fp_RefractColor;
3715         CGparameter fp_Saturation;
3716         CGparameter fp_ScreenCenterRefractReflect;
3717         CGparameter fp_ScreenScaleRefractReflect;
3718         CGparameter fp_ScreenToDepth;
3719         CGparameter fp_ShadowMap_Parameters;
3720         CGparameter fp_ShadowMap_TextureScale;
3721         CGparameter fp_SpecularPower;
3722         CGparameter fp_UserVec1;
3723         CGparameter fp_UserVec2;
3724         CGparameter fp_UserVec3;
3725         CGparameter fp_UserVec4;
3726         CGparameter fp_ViewTintColor;
3727         CGparameter fp_ViewToLight;
3728 }
3729 r_cg_permutation_t;
3730
3731 /// information about each possible shader permutation
3732 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3733 /// currently selected permutation
3734 r_cg_permutation_t *r_cg_permutation;
3735 /// storage for permutations linked in the hash table
3736 memexpandablearray_t r_cg_permutationarray;
3737
3738 #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));}}
3739
3740 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3741 {
3742         //unsigned int hashdepth = 0;
3743         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3744         r_cg_permutation_t *p;
3745         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3746         {
3747                 if (p->mode == mode && p->permutation == permutation)
3748                 {
3749                         //if (hashdepth > 10)
3750                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3751                         return p;
3752                 }
3753                 //hashdepth++;
3754         }
3755         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3756         p->mode = mode;
3757         p->permutation = permutation;
3758         p->hashnext = r_cg_permutationhash[mode][hashindex];
3759         r_cg_permutationhash[mode][hashindex] = p;
3760         //if (hashdepth > 10)
3761         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3762         return p;
3763 }
3764
3765 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3766 {
3767         char *shaderstring;
3768         if (!filename || !filename[0])
3769                 return NULL;
3770         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3771         if (shaderstring)
3772         {
3773                 if (printfromdisknotice)
3774                         Con_DPrintf("from disk %s... ", filename);
3775                 return shaderstring;
3776         }
3777         else if (!strcmp(filename, "cg/default.cg"))
3778         {
3779                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtincgshaderstring) + 1);
3780                 memcpy(shaderstring, builtincgshaderstring, strlen(builtincgshaderstring) + 1);
3781         }
3782         return shaderstring;
3783 }
3784
3785 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
3786 {
3787         int i;
3788         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
3789         int vertstrings_count = 0, vertstring_length = 0;
3790         int geomstrings_count = 0, geomstring_length = 0;
3791         int fragstrings_count = 0, fragstring_length = 0;
3792         char *t;
3793         char *vertexstring, *geometrystring, *fragmentstring;
3794         char *vertstring, *geomstring, *fragstring;
3795         const char *vertstrings_list[32+3];
3796         const char *geomstrings_list[32+3];
3797         const char *fragstrings_list[32+3];
3798         char permutationname[256];
3799         CGprofile vertexProfile;
3800         CGprofile fragmentProfile;
3801
3802         if (p->compiled)
3803                 return;
3804         p->compiled = true;
3805         p->vprogram = NULL;
3806         p->fprogram = NULL;
3807
3808         permutationname[0] = 0;
3809         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
3810         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
3811         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
3812
3813         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3814
3815         // the first pretext is which type of shader to compile as
3816         // (later these will all be bound together as a program object)
3817         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3818         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3819         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3820
3821         // the second pretext is the mode (for example a light source)
3822         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3823         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3824         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3825         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3826
3827         // now add all the permutation pretexts
3828         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3829         {
3830                 if (permutation & (1<<i))
3831                 {
3832                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3833                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3834                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3835                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3836                 }
3837                 else
3838                 {
3839                         // keep line numbers correct
3840                         vertstrings_list[vertstrings_count++] = "\n";
3841                         geomstrings_list[geomstrings_count++] = "\n";
3842                         fragstrings_list[fragstrings_count++] = "\n";
3843                 }
3844         }
3845
3846         // now append the shader text itself
3847         vertstrings_list[vertstrings_count++] = vertexstring;
3848         geomstrings_list[geomstrings_count++] = geometrystring;
3849         fragstrings_list[fragstrings_count++] = fragmentstring;
3850
3851         // if any sources were NULL, clear the respective list
3852         if (!vertexstring)
3853                 vertstrings_count = 0;
3854         if (!geometrystring)
3855                 geomstrings_count = 0;
3856         if (!fragmentstring)
3857                 fragstrings_count = 0;
3858
3859         vertstring_length = 0;
3860         for (i = 0;i < vertstrings_count;i++)
3861                 vertstring_length += strlen(vertstrings_list[i]);
3862         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
3863         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
3864                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
3865
3866         geomstring_length = 0;
3867         for (i = 0;i < geomstrings_count;i++)
3868                 geomstring_length += strlen(geomstrings_list[i]);
3869         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
3870         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
3871                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
3872
3873         fragstring_length = 0;
3874         for (i = 0;i < fragstrings_count;i++)
3875                 fragstring_length += strlen(fragstrings_list[i]);
3876         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
3877         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
3878                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
3879
3880         CHECKGLERROR
3881         CHECKCGERROR
3882         //vertexProfile = CG_PROFILE_ARBVP1;
3883         //fragmentProfile = CG_PROFILE_ARBFP1;
3884         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
3885         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
3886         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
3887         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
3888         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
3889         CHECKGLERROR
3890
3891         // compile the vertex program
3892         if (vertstring[0] && (p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, CG_PROFILE_ARBVP1, NULL, NULL)))
3893         {
3894                 CHECKCGERROR
3895                 cgCompileProgram(p->vprogram);CHECKCGERROR
3896                 if (!cgIsProgramCompiled(p->vprogram))
3897                 {
3898                         CHECKCGERROR
3899                         cgDestroyProgram(p->vprogram);CHECKCGERROR
3900                         p->vprogram = 0;
3901                 }
3902                 else
3903                 {
3904                         cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
3905                         cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
3906                         // look up all the uniform variable names we care about, so we don't
3907                         // have to look them up every time we set them
3908                         CHECKCGERROR
3909                         p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
3910                         p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
3911                         p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
3912                         p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
3913                         p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
3914                         p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
3915                         p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
3916                         p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
3917                         p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
3918                         CHECKCGERROR
3919                 }
3920         }
3921
3922         // compile the fragment program
3923         if (fragstring[0] && (p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, CG_PROFILE_ARBFP1, NULL, NULL)))
3924         {
3925                 cgCompileProgram(p->fprogram);CHECKCGERROR
3926                 if (!cgIsProgramCompiled(p->fprogram))
3927                 {
3928                         CHECKCGERROR
3929                         cgDestroyProgram(p->fprogram);CHECKCGERROR
3930                         p->fprogram = 0;
3931                 }
3932                 else
3933                 {
3934                         cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
3935                         cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
3936                         CHECKCGERROR
3937                         p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
3938                         p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
3939                         p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
3940                         p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
3941                         p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
3942                         p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
3943                         p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
3944                         p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
3945                         p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
3946                         p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
3947                         p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
3948                         p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
3949                         p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
3950                         p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
3951                         p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
3952                         p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
3953                         p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
3954                         p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
3955                         p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
3956                         p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
3957                         p->fp_Texture_ShadowMapRect      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
3958                         p->fp_Texture_ShadowMapCube      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
3959                         p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
3960                         p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
3961                         p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
3962                         p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
3963                         p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
3964                         p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
3965                         p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
3966                         p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
3967                         p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
3968                         p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
3969                         p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
3970                         p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
3971                         p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
3972                         p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
3973                         p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
3974                         p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
3975                         p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
3976                         p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
3977                         p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
3978                         p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
3979                         p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
3980                         p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
3981                         p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
3982                         p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
3983                         p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
3984                         p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
3985                         p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
3986                         p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
3987                         p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
3988                         p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
3989                         p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
3990                         p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
3991                         p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
3992                         p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
3993                         p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
3994                         p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
3995                         p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
3996                         p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
3997                         p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
3998                         p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
3999                         p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4000                         p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4001                         p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4002                         p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4003                         p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4004                         p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4005                         p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4006                         p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4007                         p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4008                         CHECKCGERROR
4009                 }
4010         }
4011
4012         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4013                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4014         else
4015                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4016
4017         // free the strings
4018         if (vertstring)
4019                 Mem_Free(vertstring);
4020         if (geomstring)
4021                 Mem_Free(geomstring);
4022         if (fragstring)
4023                 Mem_Free(fragstring);
4024         if (vertexstring)
4025                 Mem_Free(vertexstring);
4026         if (geometrystring)
4027                 Mem_Free(geometrystring);
4028         if (fragmentstring)
4029                 Mem_Free(fragmentstring);
4030 }
4031
4032 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4033 {
4034         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4035         CHECKGLERROR
4036         CHECKCGERROR
4037         if (r_cg_permutation != perm)
4038         {
4039                 r_cg_permutation = perm;
4040                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4041                 {
4042                         if (!r_cg_permutation->compiled)
4043                                 R_CG_CompilePermutation(perm, mode, permutation);
4044                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4045                         {
4046                                 // remove features until we find a valid permutation
4047                                 int i;
4048                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4049                                 {
4050                                         // reduce i more quickly whenever it would not remove any bits
4051                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4052                                         if (!(permutation & j))
4053                                                 continue;
4054                                         permutation -= j;
4055                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4056                                         if (!r_cg_permutation->compiled)
4057                                                 R_CG_CompilePermutation(perm, mode, permutation);
4058                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4059                                                 break;
4060                                 }
4061                                 if (i >= SHADERPERMUTATION_COUNT)
4062                                 {
4063                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4064                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4065                                         return; // no bit left to clear, entire mode is broken
4066                                 }
4067                         }
4068                 }
4069                 CHECKGLERROR
4070                 CHECKCGERROR
4071                 if (r_cg_permutation->vprogram)
4072                 {
4073                         //cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4074                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4075                         //cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4076                 }
4077                 else
4078                 {
4079                         //cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4080                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4081                 }
4082                 if (r_cg_permutation->fprogram)
4083                 {
4084                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4085                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4086                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4087                 }
4088                 else
4089                 {
4090                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4091                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4092                 }
4093         }
4094         CHECKCGERROR
4095         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4096 }
4097
4098 void CG_BindTexture(CGparameter param, int texnum)
4099 {
4100         cgGLSetTextureParameter(param, texnum);
4101         cgGLEnableTextureParameter(param);
4102 }
4103 #endif
4104
4105 void R_GLSL_Restart_f(void)
4106 {
4107         unsigned int i, limit;
4108         switch(vid.renderpath)
4109         {
4110         case RENDERPATH_GL20:
4111                 {
4112                         r_glsl_permutation_t *p;
4113                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4114                         for (i = 0;i < limit;i++)
4115                         {
4116                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4117                                 {
4118                                         GL_Backend_FreeProgram(p->program);
4119                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4120                                 }
4121                         }
4122                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4123                 }
4124                 break;
4125         case RENDERPATH_CGGL:
4126 #ifdef SUPPORTCG
4127                 {
4128                         r_cg_permutation_t *p;
4129                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4130                         for (i = 0;i < limit;i++)
4131                         {
4132                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4133                                 {
4134                                         if (p->vprogram)
4135                                                 cgDestroyProgram(p->vprogram);
4136                                         if (p->fprogram)
4137                                                 cgDestroyProgram(p->fprogram);
4138                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4139                                 }
4140                         }
4141                 }
4142                 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4143                 break;
4144 #endif
4145         case RENDERPATH_GL13:
4146         case RENDERPATH_GL11:
4147                 break;
4148         }
4149 }
4150
4151 void R_GLSL_DumpShader_f(void)
4152 {
4153         int i;
4154         qfile_t *file;
4155
4156         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4157         if (file)
4158         {
4159                 FS_Print(file, "/* The engine may define the following macros:\n");
4160                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4161                 for (i = 0;i < SHADERMODE_COUNT;i++)
4162                         FS_Print(file, glslshadermodeinfo[i].pretext);
4163                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4164                         FS_Print(file, shaderpermutationinfo[i].pretext);
4165                 FS_Print(file, "*/\n");
4166                 FS_Print(file, builtinshaderstring);
4167                 FS_Close(file);
4168                 Con_Printf("glsl/default.glsl written\n");
4169         }
4170         else
4171                 Con_Printf("failed to write to glsl/default.glsl\n");
4172
4173 #ifdef SUPPORTCG
4174         file = FS_OpenRealFile("cg/default.cg", "w", false);
4175         if (file)
4176         {
4177                 FS_Print(file, "/* The engine may define the following macros:\n");
4178                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4179                 for (i = 0;i < SHADERMODE_COUNT;i++)
4180                         FS_Print(file, cgshadermodeinfo[i].pretext);
4181                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4182                         FS_Print(file, shaderpermutationinfo[i].pretext);
4183                 FS_Print(file, "*/\n");
4184                 FS_Print(file, builtincgshaderstring);
4185                 FS_Close(file);
4186                 Con_Printf("cg/default.cg written\n");
4187         }
4188         else
4189                 Con_Printf("failed to write to cg/default.cg\n");
4190 #endif
4191 }
4192
4193 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4194 {
4195         if (!second)
4196                 texturemode = GL_MODULATE;
4197         switch (vid.renderpath)
4198         {
4199         case RENDERPATH_GL20:
4200                 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))));
4201                 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , R_GetTexture(first ));
4202                 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, R_GetTexture(second));
4203                 break;
4204         case RENDERPATH_CGGL:
4205 #ifdef SUPPORTCG
4206                 CHECKCGERROR
4207                 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))));
4208                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , R_GetTexture(first ));CHECKCGERROR
4209                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, R_GetTexture(second));CHECKCGERROR
4210 #endif
4211                 break;
4212         case RENDERPATH_GL13:
4213                 R_Mesh_TexBind(0, R_GetTexture(first ));
4214                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4215                 R_Mesh_TexBind(1, R_GetTexture(second));
4216                 if (second)
4217                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4218                 break;
4219         case RENDERPATH_GL11:
4220                 R_Mesh_TexBind(0, R_GetTexture(first ));
4221                 break;
4222         }
4223 }
4224
4225 void R_SetupShader_DepthOrShadow(void)
4226 {
4227         switch (vid.renderpath)
4228         {
4229         case RENDERPATH_GL20:
4230                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4231                 break;
4232         case RENDERPATH_CGGL:
4233 #ifdef SUPPORTCG
4234                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4235 #endif
4236                 break;
4237         case RENDERPATH_GL13:
4238                 R_Mesh_TexBind(0, 0);
4239                 R_Mesh_TexBind(1, 0);
4240                 break;
4241         case RENDERPATH_GL11:
4242                 R_Mesh_TexBind(0, 0);
4243                 break;
4244         }
4245 }
4246
4247 void R_SetupShader_ShowDepth(void)
4248 {
4249         switch (vid.renderpath)
4250         {
4251         case RENDERPATH_GL20:
4252                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4253                 break;
4254         case RENDERPATH_CGGL:
4255 #ifdef SUPPORTCG
4256                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4257 #endif
4258                 break;
4259         case RENDERPATH_GL13:
4260                 break;
4261         case RENDERPATH_GL11:
4262                 break;
4263         }
4264 }
4265
4266 extern qboolean r_shadow_usingdeferredprepass;
4267 extern cvar_t r_shadow_deferred_8bitrange;
4268 extern rtexture_t *r_shadow_attenuationgradienttexture;
4269 extern rtexture_t *r_shadow_attenuation2dtexture;
4270 extern rtexture_t *r_shadow_attenuation3dtexture;
4271 extern qboolean r_shadow_usingshadowmaprect;
4272 extern qboolean r_shadow_usingshadowmapcube;
4273 extern qboolean r_shadow_usingshadowmap2d;
4274 extern float r_shadow_shadowmap_texturescale[2];
4275 extern float r_shadow_shadowmap_parameters[4];
4276 extern qboolean r_shadow_shadowmapvsdct;
4277 extern qboolean r_shadow_shadowmapsampler;
4278 extern int r_shadow_shadowmappcf;
4279 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4280 extern rtexture_t *r_shadow_shadowmap2dtexture;
4281 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4282 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4283 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4284 extern int r_shadow_prepass_width;
4285 extern int r_shadow_prepass_height;
4286 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4287 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4288 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4289 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4290 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
4291 {
4292         // select a permutation of the lighting shader appropriate to this
4293         // combination of texture, entity, light source, and fogging, only use the
4294         // minimum features necessary to avoid wasting rendering time in the
4295         // fragment shader on features that are not being used
4296         unsigned int permutation = 0;
4297         unsigned int mode = 0;
4298         float m16f[16];
4299         // TODO: implement geometry-shader based shadow volumes someday
4300         if (r_glsl_offsetmapping.integer)
4301         {
4302                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4303                 if (r_glsl_offsetmapping_reliefmapping.integer)
4304                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4305         }
4306         if (rsurfacepass == RSURFPASS_BACKGROUND)
4307         {
4308                 // distorted background
4309                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4310                         mode = SHADERMODE_WATER;
4311                 else
4312                         mode = SHADERMODE_REFRACTION;
4313         }
4314         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4315         {
4316                 // normalmap (deferred prepass), may use alpha test on diffuse
4317                 mode = SHADERMODE_DEFERREDGEOMETRY;
4318                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4319                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4320                 if (r_glsl_offsetmapping.integer)
4321                 {
4322                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4323                         if (r_glsl_offsetmapping_reliefmapping.integer)
4324                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4325                 }
4326         }
4327         else if (rsurfacepass == RSURFPASS_RTLIGHT)
4328         {
4329                 // light source
4330                 mode = SHADERMODE_LIGHTSOURCE;
4331                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4332                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4333                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4334                         permutation |= SHADERPERMUTATION_CUBEFILTER;
4335                 if (diffusescale > 0)
4336                         permutation |= SHADERPERMUTATION_DIFFUSE;
4337                 if (specularscale > 0)
4338                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4339                 if (r_refdef.fogenabled)
4340                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4341                 if (rsurface.texture->colormapping)
4342                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4343                 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4344                 {
4345                         if (r_shadow_usingshadowmaprect)
4346                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4347                         if (r_shadow_usingshadowmap2d)
4348                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4349                         if (r_shadow_usingshadowmapcube)
4350                                 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4351                         else if(r_shadow_shadowmapvsdct)
4352                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4353
4354                         if (r_shadow_shadowmapsampler)
4355                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4356                         if (r_shadow_shadowmappcf > 1)
4357                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4358                         else if (r_shadow_shadowmappcf)
4359                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4360                 }
4361         }
4362         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4363         {
4364                 // unshaded geometry (fullbright or ambient model lighting)
4365                 mode = SHADERMODE_FLATCOLOR;
4366                 ambientscale = diffusescale = specularscale = 0;
4367                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4368                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4369                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4370                         permutation |= SHADERPERMUTATION_GLOW;
4371                 if (r_refdef.fogenabled)
4372                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4373                 if (rsurface.texture->colormapping)
4374                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4375                 if (r_glsl_offsetmapping.integer)
4376                 {
4377                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4378                         if (r_glsl_offsetmapping_reliefmapping.integer)
4379                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4380                 }
4381                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4382                         permutation |= SHADERPERMUTATION_REFLECTION;
4383         }
4384         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4385         {
4386                 // directional model lighting
4387                 mode = SHADERMODE_LIGHTDIRECTION;
4388                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4389                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4390                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4391                         permutation |= SHADERPERMUTATION_GLOW;
4392                 permutation |= SHADERPERMUTATION_DIFFUSE;
4393                 if (specularscale > 0)
4394                         permutation |= SHADERPERMUTATION_SPECULAR;
4395                 if (r_refdef.fogenabled)
4396                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4397                 if (rsurface.texture->colormapping)
4398                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4399                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4400                         permutation |= SHADERPERMUTATION_REFLECTION;
4401                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4402                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4403         }
4404         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
4405         {
4406                 // ambient model lighting
4407                 mode = SHADERMODE_LIGHTDIRECTION;
4408                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4409                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4410                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4411                         permutation |= SHADERPERMUTATION_GLOW;
4412                 if (r_refdef.fogenabled)
4413                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4414                 if (rsurface.texture->colormapping)
4415                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4416                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4417                         permutation |= SHADERPERMUTATION_REFLECTION;
4418                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4419                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4420         }
4421         else
4422         {
4423                 // lightmapped wall
4424                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
4425                 {
4426                         // deluxemapping (light direction texture)
4427                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
4428                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
4429                         else
4430                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4431                         permutation |= SHADERPERMUTATION_DIFFUSE;
4432                         if (specularscale > 0)
4433                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4434                 }
4435                 else if (r_glsl_deluxemapping.integer >= 2)
4436                 {
4437                         // fake deluxemapping (uniform light direction in tangentspace)
4438                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4439                         permutation |= SHADERPERMUTATION_DIFFUSE;
4440                         if (specularscale > 0)
4441                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4442                 }
4443                 else if (rsurface.uselightmaptexture)
4444                 {
4445                         // ordinary lightmapping (q1bsp, q3bsp)
4446                         mode = SHADERMODE_LIGHTMAP;
4447                 }
4448                 else
4449                 {
4450                         // ordinary vertex coloring (q3bsp)
4451                         mode = SHADERMODE_VERTEXCOLOR;
4452                 }
4453                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4454                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4455                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4456                         permutation |= SHADERPERMUTATION_GLOW;
4457                 if (r_refdef.fogenabled)
4458                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4459                 if (rsurface.texture->colormapping)
4460                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4461                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4462                         permutation |= SHADERPERMUTATION_REFLECTION;
4463                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4464                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4465         }
4466         if(permutation & SHADERPERMUTATION_SPECULAR)
4467                 if(r_shadow_glossexact.integer)
4468                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4469         if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) && r_shadow_usingdeferredprepass)
4470                 permutation |= SHADERPERMUTATION_ALPHAKILL;
4471         switch(vid.renderpath)
4472         {
4473         case RENDERPATH_GL20:
4474                 R_SetupShader_SetPermutationGLSL(mode, permutation);
4475                 if (mode == SHADERMODE_LIGHTSOURCE)
4476                 {
4477                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
4478                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
4479                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
4480                         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);
4481                         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);
4482                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, specularscale, specularscale, specularscale);
4483         
4484                         // additive passes are only darkened by fog, not tinted
4485                         if (r_glsl_permutation->loc_FogColor >= 0)
4486                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4487                         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]);
4488                         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]);
4489                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4490                 }
4491                 else
4492                 {
4493                         if (mode == SHADERMODE_FLATCOLOR)
4494                         {
4495                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
4496                         }
4497                         else if (mode == SHADERMODE_LIGHTDIRECTION)
4498                         {
4499                                 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]);
4500                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity, r_refdef.lightmapintensity, r_refdef.lightmapintensity);
4501                                 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);
4502                                 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);
4503                                 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);
4504                                 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]);
4505                                 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]);
4506                         }
4507                         else
4508                         {
4509                                 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]);
4510                                 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]);
4511                                 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);
4512                                 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);
4513                                 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);
4514                         }
4515                         // additive passes are only darkened by fog, not tinted
4516                         if (r_glsl_permutation->loc_FogColor >= 0)
4517                         {
4518                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4519                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4520                                 else
4521                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4522                         }
4523                         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);
4524                         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]);
4525                         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]);
4526                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
4527                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
4528                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
4529                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
4530                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4531                 }
4532                 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
4533                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
4534                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
4535                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
4536                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
4537                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
4538                 if (r_glsl_permutation->loc_Color_Pants >= 0)
4539                 {
4540                         if (rsurface.texture->pantstexture)
4541                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4542                         else
4543                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
4544                 }
4545                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
4546                 {
4547                         if (rsurface.texture->shirttexture)
4548                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4549                         else
4550                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
4551                 }
4552                 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]);
4553                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
4554                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
4555                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
4556                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
4557                 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]);
4558
4559         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             ,          R_GetTexture(r_texture_white                                     ));
4560         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            ,          R_GetTexture(r_texture_white                                     ));
4561         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        ,          R_GetTexture(r_texture_gammaramps                                ));
4562                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            ,          R_GetTexture(rsurface.texture->nmaptexture                       ));
4563                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             ,          R_GetTexture(rsurface.texture->basetexture                       ));
4564                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             ,          R_GetTexture(rsurface.texture->glosstexture                      ));
4565                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              ,          R_GetTexture(rsurface.texture->glowtexture                       ));
4566                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  ,          R_GetTexture(rsurface.texture->backgroundnmaptexture             ));
4567                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   ,          R_GetTexture(rsurface.texture->backgroundbasetexture             ));
4568                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   ,          R_GetTexture(rsurface.texture->backgroundglosstexture            ));
4569                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    ,          R_GetTexture(rsurface.texture->backgroundglowtexture             ));
4570                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             ,          R_GetTexture(rsurface.texture->pantstexture                      ));
4571                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             ,          R_GetTexture(rsurface.texture->shirttexture                      ));
4572                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           ,          R_GetTexture(r_texture_fogattenuation                            ));
4573                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          ,          R_GetTexture(r_texture_white                                     ));
4574                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          ,          R_GetTexture(r_texture_blanknormalmap                            ));
4575                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       ,          R_GetTexture(r_shadow_attenuationgradienttexture                 ));
4576                 if (r_glsl_permutation->loc_Texture_Refraction      >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        ,          R_GetTexture(r_texture_white                                     ));
4577                 if (r_glsl_permutation->loc_Texture_Reflection      >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        ,          R_GetTexture(r_texture_white                                     ));
4578                 if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBindAll(GL20TU_SCREENDEPTH    , 0, 0, 0, R_GetTexture(r_shadow_prepassgeometrydepthtexture                ));
4579                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBindAll(GL20TU_SCREENNORMALMAP, 0, 0, 0, R_GetTexture(r_shadow_prepassgeometrynormalmaptexture            ));
4580                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBindAll(GL20TU_SCREENDIFFUSE  , 0, 0, 0, R_GetTexture(r_shadow_prepasslightingdiffusetexture              ));
4581                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBindAll(GL20TU_SCREENSPECULAR , 0, 0, 0, R_GetTexture(r_shadow_prepasslightingspeculartexture             ));
4582                 if (rsurface.rtlight)
4583                 {
4584                         if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBindAll(GL20TU_CUBE           , 0, 0,    R_GetTexture(rsurface.rtlight->currentcubemap                    ), 0);
4585                         if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBindAll(GL20TU_SHADOWMAPRECT  , 0, 0, 0, R_GetTexture(r_shadow_shadowmaprectangletexture                  ));
4586                         if (r_shadow_usingshadowmapcube)
4587                                 if (r_glsl_permutation->loc_Texture_ShadowMapCube   >= 0) R_Mesh_TexBindAll(GL20TU_SHADOWMAPCUBE  , 0, 0,    R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]), 0);
4588                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D       ,          R_GetTexture(r_shadow_shadowmap2dtexture                         ));
4589                         if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBindAll(GL20TU_CUBEPROJECTION , 0, 0,    R_GetTexture(r_shadow_shadowmapvsdcttexture                      ), 0);
4590                 }
4591                 CHECKGLERROR
4592                 break;
4593         case RENDERPATH_CGGL:
4594 #ifdef SUPPORTCG
4595                 R_SetupShader_SetPermutationCG(mode, permutation);
4596                 if (mode == SHADERMODE_LIGHTSOURCE)
4597                 {
4598                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
4599                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4600                 }
4601                 else
4602                 {
4603                         if (mode == SHADERMODE_LIGHTDIRECTION)
4604                         {
4605                                 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
4606                         }
4607                 }
4608                 if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelviewprojection16f);CHECKCGERROR
4609                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
4610                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
4611                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4612                 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
4613                 CHECKGLERROR
4614
4615                 if (mode == SHADERMODE_LIGHTSOURCE)
4616                 {
4617                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4618                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
4619                         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
4620                         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
4621                         if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, specularscale, specularscale, specularscale);CHECKCGERROR
4622
4623                         // additive passes are only darkened by fog, not tinted
4624                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
4625                         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
4626                         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
4627                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4628                 }
4629                 else
4630                 {
4631                         if (mode == SHADERMODE_FLATCOLOR)
4632                         {
4633                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);CHECKCGERROR
4634                         }
4635                         else if (mode == SHADERMODE_LIGHTDIRECTION)
4636                         {
4637                                 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
4638                                 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, r_refdef.lightmapintensity, r_refdef.lightmapintensity, r_refdef.lightmapintensity);CHECKCGERROR
4639                                 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
4640                                 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
4641                                 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
4642                                 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
4643                                 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
4644                         }
4645                         else
4646                         {
4647                                 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
4648                                 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
4649                                 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
4650                                 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
4651                                 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
4652                         }
4653                         // additive passes are only darkened by fog, not tinted
4654                         if (r_cg_permutation->fp_FogColor)
4655                         {
4656                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4657                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
4658                                 else
4659                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4660                                 CHECKCGERROR
4661                         }
4662                         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
4663                         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
4664                         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
4665                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
4666                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
4667                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
4668                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
4669                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4670                 }
4671                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
4672                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
4673                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4674                 if (r_cg_permutation->fp_Color_Pants)
4675                 {
4676                         if (rsurface.texture->pantstexture)
4677                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4678                         else
4679                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
4680                         CHECKCGERROR
4681                 }
4682                 if (r_cg_permutation->fp_Color_Shirt)
4683                 {
4684                         if (rsurface.texture->shirttexture)
4685                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4686                         else
4687                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
4688                         CHECKCGERROR
4689                 }
4690                 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
4691                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
4692                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
4693                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
4694                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
4695                 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
4696
4697         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , R_GetTexture(r_texture_white                                     ));CHECKCGERROR
4698         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , R_GetTexture(r_texture_white                                     ));CHECKCGERROR
4699         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , R_GetTexture(r_texture_gammaramps                                ));CHECKCGERROR
4700                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , R_GetTexture(rsurface.texture->nmaptexture                       ));CHECKCGERROR
4701                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , R_GetTexture(rsurface.texture->basetexture                       ));CHECKCGERROR
4702                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , R_GetTexture(rsurface.texture->glosstexture                      ));CHECKCGERROR
4703                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , R_GetTexture(rsurface.texture->glowtexture                       ));CHECKCGERROR
4704                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, R_GetTexture(rsurface.texture->backgroundnmaptexture             ));CHECKCGERROR
4705                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , R_GetTexture(rsurface.texture->backgroundbasetexture             ));CHECKCGERROR
4706                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , R_GetTexture(rsurface.texture->backgroundglosstexture            ));CHECKCGERROR
4707                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , R_GetTexture(rsurface.texture->backgroundglowtexture             ));CHECKCGERROR
4708                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , R_GetTexture(rsurface.texture->pantstexture                      ));CHECKCGERROR
4709                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , R_GetTexture(rsurface.texture->shirttexture                      ));CHECKCGERROR
4710                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , R_GetTexture(r_texture_fogattenuation                            ));CHECKCGERROR
4711                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , R_GetTexture(r_texture_white                                     ));CHECKCGERROR
4712                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , R_GetTexture(r_texture_blanknormalmap                            ));CHECKCGERROR
4713                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , R_GetTexture(r_shadow_attenuationgradienttexture                 ));CHECKCGERROR
4714                 if (r_cg_permutation->fp_Texture_Refraction     ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction     , R_GetTexture(r_texture_white                                     ));CHECKCGERROR
4715                 if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , R_GetTexture(r_texture_white                                     ));CHECKCGERROR
4716                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , R_GetTexture(r_shadow_prepassgeometrydepthtexture                ));CHECKCGERROR
4717                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, R_GetTexture(r_shadow_prepassgeometrynormalmaptexture            ));CHECKCGERROR
4718                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , R_GetTexture(r_shadow_prepasslightingdiffusetexture              ));CHECKCGERROR
4719                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , R_GetTexture(r_shadow_prepasslightingspeculartexture             ));CHECKCGERROR
4720                 if (rsurface.rtlight)
4721                 {
4722                         if (r_cg_permutation->fp_Texture_Cube       ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , R_GetTexture(rsurface.rtlight->currentcubemap                    ));CHECKCGERROR
4723                         if (r_cg_permutation->fp_Texture_ShadowMapRect  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , R_GetTexture(r_shadow_shadowmaprectangletexture                  ));CHECKCGERROR
4724                         if (r_shadow_usingshadowmapcube)
4725                                 if (r_cg_permutation->fp_Texture_ShadowMapCube  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]));CHECKCGERROR
4726                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , R_GetTexture(r_shadow_shadowmap2dtexture                         ));CHECKCGERROR
4727                         if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , R_GetTexture(r_shadow_shadowmapvsdcttexture                      ));CHECKCGERROR
4728                 }
4729
4730                 CHECKGLERROR
4731 #endif
4732                 break;
4733         case RENDERPATH_GL13:
4734         case RENDERPATH_GL11:
4735                 break;
4736         }
4737 }
4738
4739 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
4740 {
4741         // select a permutation of the lighting shader appropriate to this
4742         // combination of texture, entity, light source, and fogging, only use the
4743         // minimum features necessary to avoid wasting rendering time in the
4744         // fragment shader on features that are not being used
4745         unsigned int permutation = 0;
4746         unsigned int mode = 0;
4747         const float *lightcolorbase = rtlight->currentcolor;
4748         float ambientscale = rtlight->ambientscale;
4749         float diffusescale = rtlight->diffusescale;
4750         float specularscale = rtlight->specularscale;
4751         // this is the location of the light in view space
4752         vec3_t viewlightorigin;
4753         // this transforms from view space (camera) to light space (cubemap)
4754         matrix4x4_t viewtolight;
4755         matrix4x4_t lighttoview;
4756         float viewtolight16f[16];
4757         float range = 1.0f / r_shadow_deferred_8bitrange.value;
4758         // light source
4759         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
4760         if (rtlight->currentcubemap != r_texture_whitecube)
4761                 permutation |= SHADERPERMUTATION_CUBEFILTER;
4762         if (diffusescale > 0)
4763                 permutation |= SHADERPERMUTATION_DIFFUSE;
4764         if (specularscale > 0)
4765         {
4766                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4767                 if (r_shadow_glossexact.integer)
4768                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4769         }
4770         if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4771         {
4772                 if (r_shadow_usingshadowmaprect)
4773                         permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4774                 if (r_shadow_usingshadowmap2d)
4775                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4776                 if (r_shadow_usingshadowmapcube)
4777                         permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4778                 else if(r_shadow_shadowmapvsdct)
4779                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4780
4781                 if (r_shadow_shadowmapsampler)
4782                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4783                 if (r_shadow_shadowmappcf > 1)
4784                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4785                 else if (r_shadow_shadowmappcf)
4786                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4787         }
4788         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
4789         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
4790         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
4791         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
4792         switch(vid.renderpath)
4793         {
4794         case RENDERPATH_GL20:
4795                 R_SetupShader_SetPermutationGLSL(mode, permutation);
4796                 if (r_glsl_permutation->loc_ModelViewMatrix           >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix          , 1, false, gl_modelview16f);
4797                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
4798                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
4799                 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);
4800                 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);
4801                 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);
4802                 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]);
4803                 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]);
4804                 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));
4805                 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]);
4806
4807                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       ,          R_GetTexture(r_shadow_attenuationgradienttexture                 ));
4808                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBindAll(GL20TU_SCREENDEPTH    , 0, 0, 0, R_GetTexture(r_shadow_prepassgeometrydepthtexture                ));
4809                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBindAll(GL20TU_SCREENNORMALMAP, 0, 0, 0, R_GetTexture(r_shadow_prepassgeometrynormalmaptexture            ));
4810                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBindAll(GL20TU_CUBE           , 0, 0,    R_GetTexture(rsurface.rtlight->currentcubemap                    ), 0);
4811                 if (r_glsl_permutation->loc_Texture_ShadowMapRect     >= 0) R_Mesh_TexBindAll(GL20TU_SHADOWMAPRECT  , 0, 0, 0, R_GetTexture(r_shadow_shadowmaprectangletexture                  ));
4812                 if (r_shadow_usingshadowmapcube)
4813                         if (r_glsl_permutation->loc_Texture_ShadowMapCube     >= 0) R_Mesh_TexBindAll(GL20TU_SHADOWMAPCUBE  , 0, 0,    R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]), 0);
4814                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D       ,          R_GetTexture(r_shadow_shadowmap2dtexture                         ));
4815                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBindAll(GL20TU_CUBEPROJECTION , 0, 0,    R_GetTexture(r_shadow_shadowmapvsdcttexture                      ), 0);
4816                 break;
4817         case RENDERPATH_CGGL:
4818 #ifdef SUPPORTCG
4819                 R_SetupShader_SetPermutationCG(mode, permutation);
4820                 if (r_cg_permutation->vp_ModelViewMatrix          ) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelviewprojection16f);CHECKCGERROR
4821                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
4822                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
4823                 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
4824                 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
4825                 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
4826                 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
4827                 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
4828                 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
4829                 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
4830
4831                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , R_GetTexture(r_shadow_attenuationgradienttexture                 ));CHECKCGERROR
4832                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , R_GetTexture(r_shadow_prepassgeometrydepthtexture                ));CHECKCGERROR
4833                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, R_GetTexture(r_shadow_prepassgeometrynormalmaptexture            ));CHECKCGERROR
4834                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , R_GetTexture(rsurface.rtlight->currentcubemap                    ));CHECKCGERROR
4835                 if (r_cg_permutation->fp_Texture_ShadowMapRect    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , R_GetTexture(r_shadow_shadowmaprectangletexture                  ));CHECKCGERROR
4836                 if (r_shadow_usingshadowmapcube)
4837                         if (r_cg_permutation->fp_Texture_ShadowMapCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]));CHECKCGERROR
4838                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , R_GetTexture(r_shadow_shadowmap2dtexture                         ));CHECKCGERROR
4839                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , R_GetTexture(r_shadow_shadowmapvsdcttexture                      ));CHECKCGERROR
4840 #endif
4841                 break;
4842         case RENDERPATH_GL13:
4843         case RENDERPATH_GL11:
4844                 break;
4845         }
4846 }
4847
4848 #define SKINFRAME_HASH 1024
4849
4850 typedef struct
4851 {
4852         int loadsequence; // incremented each level change
4853         memexpandablearray_t array;
4854         skinframe_t *hash[SKINFRAME_HASH];
4855 }
4856 r_skinframe_t;
4857 r_skinframe_t r_skinframe;
4858
4859 void R_SkinFrame_PrepareForPurge(void)
4860 {
4861         r_skinframe.loadsequence++;
4862         // wrap it without hitting zero
4863         if (r_skinframe.loadsequence >= 200)
4864                 r_skinframe.loadsequence = 1;
4865 }
4866
4867 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
4868 {
4869         if (!skinframe)
4870                 return;
4871         // mark the skinframe as used for the purging code
4872         skinframe->loadsequence = r_skinframe.loadsequence;
4873 }
4874
4875 void R_SkinFrame_Purge(void)
4876 {
4877         int i;
4878         skinframe_t *s;
4879         for (i = 0;i < SKINFRAME_HASH;i++)
4880         {
4881                 for (s = r_skinframe.hash[i];s;s = s->next)
4882                 {
4883                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
4884                         {
4885                                 if (s->merged == s->base)
4886                                         s->merged = NULL;
4887                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
4888                                 R_PurgeTexture(s->stain );s->stain  = NULL;
4889                                 R_PurgeTexture(s->merged);s->merged = NULL;
4890                                 R_PurgeTexture(s->base  );s->base   = NULL;
4891                                 R_PurgeTexture(s->pants );s->pants  = NULL;
4892                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
4893                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
4894                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
4895                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
4896                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
4897                                 s->loadsequence = 0;
4898                         }
4899                 }
4900         }
4901 }
4902
4903 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
4904         skinframe_t *item;
4905         char basename[MAX_QPATH];
4906
4907         Image_StripImageExtension(name, basename, sizeof(basename));
4908
4909         if( last == NULL ) {
4910                 int hashindex;
4911                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
4912                 item = r_skinframe.hash[hashindex];
4913         } else {
4914                 item = last->next;
4915         }
4916
4917         // linearly search through the hash bucket
4918         for( ; item ; item = item->next ) {
4919                 if( !strcmp( item->basename, basename ) ) {
4920                         return item;
4921                 }
4922         }
4923         return NULL;
4924 }
4925
4926 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
4927 {
4928         skinframe_t *item;
4929         int hashindex;
4930         char basename[MAX_QPATH];
4931
4932         Image_StripImageExtension(name, basename, sizeof(basename));
4933
4934         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
4935         for (item = r_skinframe.hash[hashindex];item;item = item->next)
4936                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
4937                         break;
4938
4939         if (!item) {
4940                 rtexture_t *dyntexture;
4941                 // check whether its a dynamic texture
4942                 dyntexture = CL_GetDynTexture( basename );
4943                 if (!add && !dyntexture)
4944                         return NULL;
4945                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
4946                 memset(item, 0, sizeof(*item));
4947                 strlcpy(item->basename, basename, sizeof(item->basename));
4948                 item->base = dyntexture; // either NULL or dyntexture handle
4949                 item->textureflags = textureflags;
4950                 item->comparewidth = comparewidth;
4951                 item->compareheight = compareheight;
4952                 item->comparecrc = comparecrc;
4953                 item->next = r_skinframe.hash[hashindex];
4954                 r_skinframe.hash[hashindex] = item;
4955         }
4956         else if( item->base == NULL )
4957         {
4958                 rtexture_t *dyntexture;
4959                 // check whether its a dynamic texture
4960                 // 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]
4961                 dyntexture = CL_GetDynTexture( basename );
4962                 item->base = dyntexture; // either NULL or dyntexture handle
4963         }
4964
4965         R_SkinFrame_MarkUsed(item);
4966         return item;
4967 }
4968
4969 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
4970         { \
4971                 unsigned long long avgcolor[5], wsum; \
4972                 int pix, comp, w; \
4973                 avgcolor[0] = 0; \
4974                 avgcolor[1] = 0; \
4975                 avgcolor[2] = 0; \
4976                 avgcolor[3] = 0; \
4977                 avgcolor[4] = 0; \
4978                 wsum = 0; \
4979                 for(pix = 0; pix < cnt; ++pix) \
4980                 { \
4981                         w = 0; \
4982                         for(comp = 0; comp < 3; ++comp) \
4983                                 w += getpixel; \
4984                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
4985                         { \
4986                                 ++wsum; \
4987                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
4988                                 w = getpixel; \
4989                                 for(comp = 0; comp < 3; ++comp) \
4990                                         avgcolor[comp] += getpixel * w; \
4991                                 avgcolor[3] += w; \
4992                         } \
4993                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
4994                         avgcolor[4] += getpixel; \
4995                 } \
4996                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
4997                         avgcolor[3] = 1; \
4998                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
4999                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5000                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5001                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5002         }
5003
5004 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5005 {
5006         int j;
5007         unsigned char *pixels;
5008         unsigned char *bumppixels;
5009         unsigned char *basepixels = NULL;
5010         int basepixels_width;
5011         int basepixels_height;
5012         skinframe_t *skinframe;
5013
5014         if (cls.state == ca_dedicated)
5015                 return NULL;
5016
5017         // return an existing skinframe if already loaded
5018         // if loading of the first image fails, don't make a new skinframe as it
5019         // would cause all future lookups of this to be missing
5020         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5021         if (skinframe && skinframe->base)
5022                 return skinframe;
5023
5024         basepixels = loadimagepixelsbgra(name, complain, true);
5025         if (basepixels == NULL)
5026                 return NULL;
5027
5028         if (developer_loading.integer)
5029                 Con_Printf("loading skin \"%s\"\n", name);
5030
5031         // we've got some pixels to store, so really allocate this new texture now
5032         if (!skinframe)
5033                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5034         skinframe->stain = NULL;
5035         skinframe->merged = NULL;
5036         skinframe->base = r_texture_notexture;
5037         skinframe->pants = NULL;
5038         skinframe->shirt = NULL;
5039         skinframe->nmap = r_texture_blanknormalmap;
5040         skinframe->gloss = NULL;
5041         skinframe->glow = NULL;
5042         skinframe->fog = NULL;
5043         skinframe->hasalpha = false;
5044
5045         basepixels_width = image_width;
5046         basepixels_height = image_height;
5047         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);
5048
5049         if (textureflags & TEXF_ALPHA)
5050         {
5051                 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5052                 {
5053                         if (basepixels[j] < 255)
5054                         {
5055                                 skinframe->hasalpha = true;
5056                                 break;
5057                         }
5058                 }
5059                 if (r_loadfog && skinframe->hasalpha)
5060                 {
5061                         // has transparent pixels
5062                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5063                         for (j = 0;j < image_width * image_height * 4;j += 4)
5064                         {
5065                                 pixels[j+0] = 255;
5066                                 pixels[j+1] = 255;
5067                                 pixels[j+2] = 255;
5068                                 pixels[j+3] = basepixels[j+3];
5069                         }
5070                         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);
5071                         Mem_Free(pixels);
5072                 }
5073         }
5074
5075         R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5076         //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]);
5077
5078         // _norm is the name used by tenebrae and has been adopted as standard
5079         if (r_loadnormalmap)
5080         {
5081                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
5082                 {
5083                         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);
5084                         Mem_Free(pixels);
5085                         pixels = NULL;
5086                 }
5087                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
5088                 {
5089                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5090                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5091                         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);
5092                         Mem_Free(pixels);
5093                         Mem_Free(bumppixels);
5094                 }
5095                 else if (r_shadow_bumpscale_basetexture.value > 0)
5096                 {
5097                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5098                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5099                         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);
5100                         Mem_Free(pixels);
5101                 }
5102         }
5103         // _luma is supported for tenebrae compatibility
5104         // (I think it's a very stupid name, but oh well)
5105         // _glow is the preferred name
5106         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;}
5107         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;}
5108         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;}
5109         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;}
5110
5111         if (basepixels)
5112                 Mem_Free(basepixels);
5113
5114         return skinframe;
5115 }
5116
5117 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
5118 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
5119 {
5120         int i;
5121         unsigned char *temp1, *temp2;
5122         skinframe_t *skinframe;
5123
5124         if (cls.state == ca_dedicated)
5125                 return NULL;
5126
5127         // if already loaded just return it, otherwise make a new skinframe
5128         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
5129         if (skinframe && skinframe->base)
5130                 return skinframe;
5131
5132         skinframe->stain = NULL;
5133         skinframe->merged = NULL;
5134         skinframe->base = r_texture_notexture;
5135         skinframe->pants = NULL;
5136         skinframe->shirt = NULL;
5137         skinframe->nmap = r_texture_blanknormalmap;
5138         skinframe->gloss = NULL;
5139         skinframe->glow = NULL;
5140         skinframe->fog = NULL;
5141         skinframe->hasalpha = false;
5142
5143         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5144         if (!skindata)
5145                 return NULL;
5146
5147         if (developer_loading.integer)
5148                 Con_Printf("loading 32bit skin \"%s\"\n", name);
5149
5150         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
5151         {
5152                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5153                 temp2 = temp1 + width * height * 4;
5154                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5155                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5156                 Mem_Free(temp1);
5157         }
5158         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5159         if (textureflags & TEXF_ALPHA)
5160         {
5161                 for (i = 3;i < width * height * 4;i += 4)
5162                 {
5163                         if (skindata[i] < 255)
5164                         {
5165                                 skinframe->hasalpha = true;
5166                                 break;
5167                         }
5168                 }
5169                 if (r_loadfog && skinframe->hasalpha)
5170                 {
5171                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
5172                         memcpy(fogpixels, skindata, width * height * 4);
5173                         for (i = 0;i < width * height * 4;i += 4)
5174                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
5175                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5176                         Mem_Free(fogpixels);
5177                 }
5178         }
5179
5180         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
5181         //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]);
5182
5183         return skinframe;
5184 }
5185
5186 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
5187 {
5188         int i;
5189         int featuresmask;
5190         skinframe_t *skinframe;
5191
5192         if (cls.state == ca_dedicated)
5193                 return NULL;
5194
5195         // if already loaded just return it, otherwise make a new skinframe
5196         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5197         if (skinframe && skinframe->base)
5198                 return skinframe;
5199
5200         skinframe->stain = NULL;
5201         skinframe->merged = NULL;
5202         skinframe->base = r_texture_notexture;
5203         skinframe->pants = NULL;
5204         skinframe->shirt = NULL;
5205         skinframe->nmap = r_texture_blanknormalmap;
5206         skinframe->gloss = NULL;
5207         skinframe->glow = NULL;
5208         skinframe->fog = NULL;
5209         skinframe->hasalpha = false;
5210
5211         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5212         if (!skindata)
5213                 return NULL;
5214
5215         if (developer_loading.integer)
5216                 Con_Printf("loading quake skin \"%s\"\n", name);
5217
5218         // 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)
5219         skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
5220         memcpy(skinframe->qpixels, skindata, width*height);
5221         skinframe->qwidth = width;
5222         skinframe->qheight = height;
5223
5224         featuresmask = 0;
5225         for (i = 0;i < width * height;i++)
5226                 featuresmask |= palette_featureflags[skindata[i]];
5227
5228         skinframe->hasalpha = false;
5229         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
5230         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
5231         skinframe->qgeneratemerged = true;
5232         skinframe->qgeneratebase = skinframe->qhascolormapping;
5233         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
5234
5235         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
5236         //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]);
5237
5238         return skinframe;
5239 }
5240
5241 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
5242 {
5243         int width;
5244         int height;
5245         unsigned char *skindata;
5246
5247         if (!skinframe->qpixels)
5248                 return;
5249
5250         if (!skinframe->qhascolormapping)
5251                 colormapped = false;
5252
5253         if (colormapped)
5254         {
5255                 if (!skinframe->qgeneratebase)
5256                         return;
5257         }
5258         else
5259         {
5260                 if (!skinframe->qgeneratemerged)
5261                         return;
5262         }
5263
5264         width = skinframe->qwidth;
5265         height = skinframe->qheight;
5266         skindata = skinframe->qpixels;
5267
5268         if (skinframe->qgeneratenmap)
5269         {
5270                 unsigned char *temp1, *temp2;
5271                 skinframe->qgeneratenmap = false;
5272                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5273                 temp2 = temp1 + width * height * 4;
5274                 // use either a custom palette or the quake palette
5275                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
5276                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5277                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5278                 Mem_Free(temp1);
5279         }
5280
5281         if (skinframe->qgenerateglow)
5282         {
5283                 skinframe->qgenerateglow = false;
5284                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
5285         }
5286
5287         if (colormapped)
5288         {
5289                 skinframe->qgeneratebase = false;
5290                 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);
5291                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
5292                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
5293         }
5294         else
5295         {
5296                 skinframe->qgeneratemerged = false;
5297                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
5298         }
5299
5300         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
5301         {
5302                 Mem_Free(skinframe->qpixels);
5303                 skinframe->qpixels = NULL;
5304         }
5305 }
5306
5307 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)
5308 {
5309         int i;
5310         skinframe_t *skinframe;
5311
5312         if (cls.state == ca_dedicated)
5313                 return NULL;
5314
5315         // if already loaded just return it, otherwise make a new skinframe
5316         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5317         if (skinframe && skinframe->base)
5318                 return skinframe;
5319
5320         skinframe->stain = NULL;
5321         skinframe->merged = NULL;
5322         skinframe->base = r_texture_notexture;
5323         skinframe->pants = NULL;
5324         skinframe->shirt = NULL;
5325         skinframe->nmap = r_texture_blanknormalmap;
5326         skinframe->gloss = NULL;
5327         skinframe->glow = NULL;
5328         skinframe->fog = NULL;
5329         skinframe->hasalpha = false;
5330
5331         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5332         if (!skindata)
5333                 return NULL;
5334
5335         if (developer_loading.integer)
5336                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
5337
5338         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
5339         if (textureflags & TEXF_ALPHA)
5340         {
5341                 for (i = 0;i < width * height;i++)
5342                 {
5343                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
5344                         {
5345                                 skinframe->hasalpha = true;
5346                                 break;
5347                         }
5348                 }
5349                 if (r_loadfog && skinframe->hasalpha)
5350                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
5351         }
5352
5353         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
5354         //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]);
5355
5356         return skinframe;
5357 }
5358
5359 skinframe_t *R_SkinFrame_LoadMissing(void)
5360 {
5361         skinframe_t *skinframe;
5362
5363         if (cls.state == ca_dedicated)
5364                 return NULL;
5365
5366         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
5367         skinframe->stain = NULL;
5368         skinframe->merged = NULL;
5369         skinframe->base = r_texture_notexture;
5370         skinframe->pants = NULL;
5371         skinframe->shirt = NULL;
5372         skinframe->nmap = r_texture_blanknormalmap;
5373         skinframe->gloss = NULL;
5374         skinframe->glow = NULL;
5375         skinframe->fog = NULL;
5376         skinframe->hasalpha = false;
5377
5378         skinframe->avgcolor[0] = rand() / RAND_MAX;
5379         skinframe->avgcolor[1] = rand() / RAND_MAX;
5380         skinframe->avgcolor[2] = rand() / RAND_MAX;
5381         skinframe->avgcolor[3] = 1;
5382
5383         return skinframe;
5384 }
5385
5386 void R_Main_FreeViewCache(void)
5387 {
5388         if (r_refdef.viewcache.entityvisible)
5389                 Mem_Free(r_refdef.viewcache.entityvisible);
5390         if (r_refdef.viewcache.world_pvsbits)
5391                 Mem_Free(r_refdef.viewcache.world_pvsbits);
5392         if (r_refdef.viewcache.world_leafvisible)
5393                 Mem_Free(r_refdef.viewcache.world_leafvisible);
5394         if (r_refdef.viewcache.world_surfacevisible)
5395                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
5396         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
5397 }
5398
5399 void R_Main_ResizeViewCache(void)
5400 {
5401         int numentities = r_refdef.scene.numentities;
5402         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
5403         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
5404         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
5405         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
5406         if (r_refdef.viewcache.maxentities < numentities)
5407         {
5408                 r_refdef.viewcache.maxentities = numentities;
5409                 if (r_refdef.viewcache.entityvisible)
5410                         Mem_Free(r_refdef.viewcache.entityvisible);
5411                 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
5412         }
5413         if (r_refdef.viewcache.world_numclusters != numclusters)
5414         {
5415                 r_refdef.viewcache.world_numclusters = numclusters;
5416                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
5417                 if (r_refdef.viewcache.world_pvsbits)
5418                         Mem_Free(r_refdef.viewcache.world_pvsbits);
5419                 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
5420         }
5421         if (r_refdef.viewcache.world_numleafs != numleafs)
5422         {
5423                 r_refdef.viewcache.world_numleafs = numleafs;
5424                 if (r_refdef.viewcache.world_leafvisible)
5425                         Mem_Free(r_refdef.viewcache.world_leafvisible);
5426                 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
5427         }
5428         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
5429         {
5430                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
5431                 if (r_refdef.viewcache.world_surfacevisible)
5432                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
5433                 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
5434         }
5435 }
5436
5437 extern rtexture_t *loadingscreentexture;
5438 void gl_main_start(void)
5439 {
5440         loadingscreentexture = NULL;
5441         r_texture_blanknormalmap = NULL;
5442         r_texture_white = NULL;
5443         r_texture_grey128 = NULL;
5444         r_texture_black = NULL;
5445         r_texture_whitecube = NULL;
5446         r_texture_normalizationcube = NULL;
5447         r_texture_fogattenuation = NULL;
5448         r_texture_gammaramps = NULL;
5449
5450         switch(vid.renderpath)
5451         {
5452         case RENDERPATH_GL20:
5453         case RENDERPATH_CGGL:
5454                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5455                 Cvar_SetValueQuick(&gl_combine, 1);
5456                 Cvar_SetValueQuick(&r_glsl, 1);
5457                 r_loadnormalmap = true;
5458                 r_loadgloss = true;
5459                 r_loadfog = false;
5460                 break;
5461         case RENDERPATH_GL13:
5462                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5463                 Cvar_SetValueQuick(&gl_combine, 1);
5464                 Cvar_SetValueQuick(&r_glsl, 0);
5465                 r_loadnormalmap = false;
5466                 r_loadgloss = false;
5467                 r_loadfog = true;
5468                 break;
5469         case RENDERPATH_GL11:
5470                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5471                 Cvar_SetValueQuick(&gl_combine, 0);
5472                 Cvar_SetValueQuick(&r_glsl, 0);
5473                 r_loadnormalmap = false;
5474                 r_loadgloss = false;
5475                 r_loadfog = true;
5476                 break;
5477         }
5478
5479         R_AnimCache_Free();
5480         R_FrameData_Reset();
5481
5482         r_numqueries = 0;
5483         r_maxqueries = 0;
5484         memset(r_queries, 0, sizeof(r_queries));
5485
5486         r_qwskincache = NULL;
5487         r_qwskincache_size = 0;
5488
5489         // set up r_skinframe loading system for textures
5490         memset(&r_skinframe, 0, sizeof(r_skinframe));
5491         r_skinframe.loadsequence = 1;
5492         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
5493
5494         r_main_texturepool = R_AllocTexturePool();
5495         R_BuildBlankTextures();
5496         R_BuildNoTexture();
5497         if (vid.support.arb_texture_cube_map)
5498         {
5499                 R_BuildWhiteCube();
5500                 R_BuildNormalizationCube();
5501         }
5502         r_texture_fogattenuation = NULL;
5503         r_texture_gammaramps = NULL;
5504         //r_texture_fogintensity = NULL;
5505         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
5506         memset(&r_waterstate, 0, sizeof(r_waterstate));
5507         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5508         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
5509 #ifdef SUPPORTCG
5510         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5511         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
5512 #endif
5513         memset(&r_svbsp, 0, sizeof (r_svbsp));
5514
5515         r_refdef.fogmasktable_density = 0;
5516 }
5517
5518 void gl_main_shutdown(void)
5519 {
5520         R_AnimCache_Free();
5521         R_FrameData_Reset();
5522
5523         R_Main_FreeViewCache();
5524
5525         if (r_maxqueries)
5526                 qglDeleteQueriesARB(r_maxqueries, r_queries);
5527
5528         r_numqueries = 0;
5529         r_maxqueries = 0;
5530         memset(r_queries, 0, sizeof(r_queries));
5531
5532         r_qwskincache = NULL;
5533         r_qwskincache_size = 0;
5534
5535         // clear out the r_skinframe state
5536         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
5537         memset(&r_skinframe, 0, sizeof(r_skinframe));
5538
5539         if (r_svbsp.nodes)
5540                 Mem_Free(r_svbsp.nodes);
5541         memset(&r_svbsp, 0, sizeof (r_svbsp));
5542         R_FreeTexturePool(&r_main_texturepool);
5543         loadingscreentexture = NULL;
5544         r_texture_blanknormalmap = NULL;
5545         r_texture_white = NULL;
5546         r_texture_grey128 = NULL;
5547         r_texture_black = NULL;
5548         r_texture_whitecube = NULL;
5549         r_texture_normalizationcube = NULL;
5550         r_texture_fogattenuation = NULL;
5551         r_texture_gammaramps = NULL;
5552         //r_texture_fogintensity = NULL;
5553         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
5554         memset(&r_waterstate, 0, sizeof(r_waterstate));
5555         R_GLSL_Restart_f();
5556 }
5557
5558 extern void CL_ParseEntityLump(char *entitystring);
5559 void gl_main_newmap(void)
5560 {
5561         // FIXME: move this code to client
5562         int l;
5563         char *entities, entname[MAX_QPATH];
5564         if (r_qwskincache)
5565                 Mem_Free(r_qwskincache);
5566         r_qwskincache = NULL;
5567         r_qwskincache_size = 0;
5568         if (cl.worldmodel)
5569         {
5570                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
5571                 l = (int)strlen(entname) - 4;
5572                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
5573                 {
5574                         memcpy(entname + l, ".ent", 5);
5575                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
5576                         {
5577                                 CL_ParseEntityLump(entities);
5578                                 Mem_Free(entities);
5579                                 return;
5580                         }
5581                 }
5582                 if (cl.worldmodel->brush.entities)
5583                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
5584         }
5585         R_Main_FreeViewCache();
5586
5587         R_FrameData_Reset();
5588 }
5589
5590 void GL_Main_Init(void)
5591 {
5592         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
5593
5594         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
5595         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
5596         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
5597         if (gamemode == GAME_NEHAHRA)
5598         {
5599                 Cvar_RegisterVariable (&gl_fogenable);
5600                 Cvar_RegisterVariable (&gl_fogdensity);
5601                 Cvar_RegisterVariable (&gl_fogred);
5602                 Cvar_RegisterVariable (&gl_foggreen);
5603                 Cvar_RegisterVariable (&gl_fogblue);
5604                 Cvar_RegisterVariable (&gl_fogstart);
5605                 Cvar_RegisterVariable (&gl_fogend);
5606                 Cvar_RegisterVariable (&gl_skyclip);
5607         }
5608         Cvar_RegisterVariable(&r_motionblur);
5609         Cvar_RegisterVariable(&r_motionblur_maxblur);
5610         Cvar_RegisterVariable(&r_motionblur_bmin);
5611         Cvar_RegisterVariable(&r_motionblur_vmin);
5612         Cvar_RegisterVariable(&r_motionblur_vmax);
5613         Cvar_RegisterVariable(&r_motionblur_vcoeff);
5614         Cvar_RegisterVariable(&r_motionblur_randomize);
5615         Cvar_RegisterVariable(&r_damageblur);
5616         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
5617         Cvar_RegisterVariable(&r_equalize_entities_minambient);
5618         Cvar_RegisterVariable(&r_equalize_entities_by);
5619         Cvar_RegisterVariable(&r_equalize_entities_to);
5620         Cvar_RegisterVariable(&r_depthfirst);
5621         Cvar_RegisterVariable(&r_useinfinitefarclip);
5622         Cvar_RegisterVariable(&r_farclip_base);
5623         Cvar_RegisterVariable(&r_farclip_world);
5624         Cvar_RegisterVariable(&r_nearclip);
5625         Cvar_RegisterVariable(&r_showbboxes);
5626         Cvar_RegisterVariable(&r_showsurfaces);
5627         Cvar_RegisterVariable(&r_showtris);
5628         Cvar_RegisterVariable(&r_shownormals);
5629         Cvar_RegisterVariable(&r_showlighting);
5630         Cvar_RegisterVariable(&r_showshadowvolumes);
5631         Cvar_RegisterVariable(&r_showcollisionbrushes);
5632         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
5633         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
5634         Cvar_RegisterVariable(&r_showdisabledepthtest);
5635         Cvar_RegisterVariable(&r_drawportals);
5636         Cvar_RegisterVariable(&r_drawentities);
5637         Cvar_RegisterVariable(&r_cullentities_trace);
5638         Cvar_RegisterVariable(&r_cullentities_trace_samples);
5639         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
5640         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
5641         Cvar_RegisterVariable(&r_cullentities_trace_delay);
5642         Cvar_RegisterVariable(&r_drawviewmodel);
5643         Cvar_RegisterVariable(&r_speeds);
5644         Cvar_RegisterVariable(&r_fullbrights);
5645         Cvar_RegisterVariable(&r_wateralpha);
5646         Cvar_RegisterVariable(&r_dynamic);
5647         Cvar_RegisterVariable(&r_fullbright);
5648         Cvar_RegisterVariable(&r_shadows);
5649         Cvar_RegisterVariable(&r_shadows_darken);
5650         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
5651         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
5652         Cvar_RegisterVariable(&r_shadows_throwdistance);
5653         Cvar_RegisterVariable(&r_shadows_throwdirection);
5654         Cvar_RegisterVariable(&r_q1bsp_skymasking);
5655         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
5656         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
5657         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
5658         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
5659         Cvar_RegisterVariable(&r_fog_exp2);
5660         Cvar_RegisterVariable(&r_drawfog);
5661         Cvar_RegisterVariable(&r_transparentdepthmasking);
5662         Cvar_RegisterVariable(&r_textureunits);
5663         Cvar_RegisterVariable(&gl_combine);
5664         Cvar_RegisterVariable(&r_glsl);
5665         Cvar_RegisterVariable(&r_glsl_deluxemapping);
5666         Cvar_RegisterVariable(&r_glsl_offsetmapping);
5667         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
5668         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
5669         Cvar_RegisterVariable(&r_glsl_postprocess);
5670         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
5671         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
5672         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
5673         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
5674         Cvar_RegisterVariable(&r_water);
5675         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
5676         Cvar_RegisterVariable(&r_water_clippingplanebias);
5677         Cvar_RegisterVariable(&r_water_refractdistort);
5678         Cvar_RegisterVariable(&r_water_reflectdistort);
5679         Cvar_RegisterVariable(&r_lerpsprites);
5680         Cvar_RegisterVariable(&r_lerpmodels);
5681         Cvar_RegisterVariable(&r_lerplightstyles);
5682         Cvar_RegisterVariable(&r_waterscroll);
5683         Cvar_RegisterVariable(&r_bloom);
5684         Cvar_RegisterVariable(&r_bloom_colorscale);
5685         Cvar_RegisterVariable(&r_bloom_brighten);
5686         Cvar_RegisterVariable(&r_bloom_blur);
5687         Cvar_RegisterVariable(&r_bloom_resolution);
5688         Cvar_RegisterVariable(&r_bloom_colorexponent);
5689         Cvar_RegisterVariable(&r_bloom_colorsubtract);
5690         Cvar_RegisterVariable(&r_hdr);
5691         Cvar_RegisterVariable(&r_hdr_scenebrightness);
5692         Cvar_RegisterVariable(&r_hdr_glowintensity);
5693         Cvar_RegisterVariable(&r_hdr_range);
5694         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
5695         Cvar_RegisterVariable(&developer_texturelogging);
5696         Cvar_RegisterVariable(&gl_lightmaps);
5697         Cvar_RegisterVariable(&r_test);
5698         Cvar_RegisterVariable(&r_batchmode);
5699         Cvar_RegisterVariable(&r_glsl_saturation);
5700         Cvar_RegisterVariable(&r_framedatasize);
5701         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
5702                 Cvar_SetValue("r_fullbrights", 0);
5703         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
5704
5705         Cvar_RegisterVariable(&r_track_sprites);
5706         Cvar_RegisterVariable(&r_track_sprites_flags);
5707         Cvar_RegisterVariable(&r_track_sprites_scalew);
5708         Cvar_RegisterVariable(&r_track_sprites_scaleh);
5709 }
5710
5711 extern void R_Textures_Init(void);
5712 extern void GL_Draw_Init(void);
5713 extern void GL_Main_Init(void);
5714 extern void R_Shadow_Init(void);
5715 extern void R_Sky_Init(void);
5716 extern void GL_Surf_Init(void);
5717 extern void R_Particles_Init(void);
5718 extern void R_Explosion_Init(void);
5719 extern void gl_backend_init(void);
5720 extern void Sbar_Init(void);
5721 extern void R_LightningBeams_Init(void);
5722 extern void Mod_RenderInit(void);
5723 extern void Font_Init(void);
5724
5725 void Render_Init(void)
5726 {
5727         gl_backend_init();
5728         R_Textures_Init();
5729         GL_Main_Init();
5730         Font_Init();
5731         GL_Draw_Init();
5732         R_Shadow_Init();
5733         R_Sky_Init();
5734         GL_Surf_Init();
5735         Sbar_Init();
5736         R_Particles_Init();
5737         R_Explosion_Init();
5738         R_LightningBeams_Init();
5739         Mod_RenderInit();
5740 }
5741
5742 /*
5743 ===============
5744 GL_Init
5745 ===============
5746 */
5747 extern char *ENGINE_EXTENSIONS;
5748 void GL_Init (void)
5749 {
5750         gl_renderer = (const char *)qglGetString(GL_RENDERER);
5751         gl_vendor = (const char *)qglGetString(GL_VENDOR);
5752         gl_version = (const char *)qglGetString(GL_VERSION);
5753         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
5754
5755         if (!gl_extensions)
5756                 gl_extensions = "";
5757         if (!gl_platformextensions)
5758                 gl_platformextensions = "";
5759
5760         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
5761         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
5762         Con_Printf("GL_VERSION: %s\n", gl_version);
5763         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
5764         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
5765
5766         VID_CheckExtensions();
5767
5768         // LordHavoc: report supported extensions
5769         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
5770
5771         // clear to black (loading plaque will be seen over this)
5772         CHECKGLERROR
5773         qglClearColor(0,0,0,1);CHECKGLERROR
5774         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
5775 }
5776
5777 int R_CullBox(const vec3_t mins, const vec3_t maxs)
5778 {
5779         int i;
5780         mplane_t *p;
5781         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5782         {
5783                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
5784                 if (i == 4)
5785                         continue;
5786                 p = r_refdef.view.frustum + i;
5787                 switch(p->signbits)
5788                 {
5789                 default:
5790                 case 0:
5791                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5792                                 return true;
5793                         break;
5794                 case 1:
5795                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5796                                 return true;
5797                         break;
5798                 case 2:
5799                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5800                                 return true;
5801                         break;
5802                 case 3:
5803                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5804                                 return true;
5805                         break;
5806                 case 4:
5807                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5808                                 return true;
5809                         break;
5810                 case 5:
5811                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5812                                 return true;
5813                         break;
5814                 case 6:
5815                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5816                                 return true;
5817                         break;
5818                 case 7:
5819                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5820                                 return true;
5821                         break;
5822                 }
5823         }
5824         return false;
5825 }
5826
5827 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
5828 {
5829         int i;
5830         const mplane_t *p;
5831         for (i = 0;i < numplanes;i++)
5832         {
5833                 p = planes + i;
5834                 switch(p->signbits)
5835                 {
5836                 default:
5837                 case 0:
5838                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5839                                 return true;
5840                         break;
5841                 case 1:
5842                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5843                                 return true;
5844                         break;
5845                 case 2:
5846                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5847                                 return true;
5848                         break;
5849                 case 3:
5850                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5851                                 return true;
5852                         break;
5853                 case 4:
5854                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5855                                 return true;
5856                         break;
5857                 case 5:
5858                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5859                                 return true;
5860                         break;
5861                 case 6:
5862                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5863                                 return true;
5864                         break;
5865                 case 7:
5866                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5867                                 return true;
5868                         break;
5869                 }
5870         }
5871         return false;
5872 }
5873
5874 //==================================================================================
5875
5876 // LordHavoc: this stores temporary data used within the same frame
5877
5878 qboolean r_framedata_failed;
5879 static size_t r_framedata_size;
5880 static size_t r_framedata_current;
5881 static void *r_framedata_base;
5882
5883 void R_FrameData_Reset(void)
5884 {
5885         if (r_framedata_base);
5886                 Mem_Free(r_framedata_base);
5887         r_framedata_base = NULL;
5888         r_framedata_size = 0;
5889         r_framedata_current = 0;
5890         r_framedata_failed = false;
5891 }
5892
5893 void R_FrameData_NewFrame(void)
5894 {
5895         size_t wantedsize;
5896         if (r_framedata_failed)
5897                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
5898         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
5899         wantedsize = bound(65536, wantedsize, 128*1024*1024);
5900         if (r_framedata_size != wantedsize)
5901         {
5902                 r_framedata_size = wantedsize;
5903                 if (r_framedata_base);
5904                         Mem_Free(r_framedata_base);
5905                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
5906         }
5907         r_framedata_current = 0;
5908         r_framedata_failed = false;
5909 }
5910
5911 void *R_FrameData_Alloc(size_t size)
5912 {
5913         void *data;
5914
5915         // align to 16 byte boundary
5916         size = (size + 15) & ~15;
5917         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
5918         r_framedata_current += size;
5919
5920         // check overflow
5921         if (r_framedata_current > r_framedata_size)
5922                 r_framedata_failed = true;
5923
5924         // return NULL on everything after a failure
5925         if (r_framedata_failed)
5926                 return NULL;
5927
5928         return data;
5929 }
5930
5931 void *R_FrameData_Store(size_t size, void *data)
5932 {
5933         void *d = R_FrameData_Alloc(size);
5934         if (d)
5935                 memcpy(d, data, size);
5936         return d;
5937 }
5938
5939 //==================================================================================
5940
5941 // LordHavoc: animcache originally written by Echon, rewritten since then
5942
5943 /**
5944  * Animation cache prevents re-generating mesh data for an animated model
5945  * multiple times in one frame for lighting, shadowing, reflections, etc.
5946  */
5947
5948 void R_AnimCache_Free(void)
5949 {
5950 }
5951
5952 void R_AnimCache_ClearCache(void)
5953 {
5954         int i;
5955         entity_render_t *ent;
5956
5957         for (i = 0;i < r_refdef.scene.numentities;i++)
5958         {
5959                 ent = r_refdef.scene.entities[i];
5960                 ent->animcache_vertex3f = NULL;
5961                 ent->animcache_normal3f = NULL;
5962                 ent->animcache_svector3f = NULL;
5963                 ent->animcache_tvector3f = NULL;
5964         }
5965 }
5966
5967 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
5968 {
5969         dp_model_t *model = ent->model;
5970         int numvertices;
5971         // see if it's already cached this frame
5972         if (ent->animcache_vertex3f)
5973         {
5974                 // add normals/tangents if needed
5975                 if (wantnormals || wanttangents)
5976                 {
5977                         if (ent->animcache_normal3f)
5978                                 wantnormals = false;
5979                         if (ent->animcache_svector3f)
5980                                 wanttangents = false;
5981                         if (wantnormals || wanttangents)
5982                         {
5983                                 numvertices = model->surfmesh.num_vertices;
5984                                 if (wantnormals)
5985                                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
5986                                 if (wanttangents)
5987                                 {
5988                                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
5989                                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
5990                                 }
5991                                 if (!r_framedata_failed)
5992                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
5993                         }
5994                 }
5995         }
5996         else
5997         {
5998                 // see if this ent is worth caching
5999                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
6000                         return false;
6001                 // get some memory for this entity and generate mesh data
6002                 numvertices = model->surfmesh.num_vertices;
6003                 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6004                 if (wantnormals)
6005                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6006                 if (wanttangents)
6007                 {
6008                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6009                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6010                 }
6011                 if (!r_framedata_failed)
6012                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
6013         }
6014         return !r_framedata_failed;
6015 }
6016
6017 void R_AnimCache_CacheVisibleEntities(void)
6018 {
6019         int i;
6020         qboolean wantnormals = !r_showsurfaces.integer;
6021         qboolean wanttangents = !r_showsurfaces.integer;
6022
6023         switch(vid.renderpath)
6024         {
6025         case RENDERPATH_GL20:
6026         case RENDERPATH_CGGL:
6027                 break;
6028         case RENDERPATH_GL13:
6029         case RENDERPATH_GL11:
6030                 wanttangents = false;
6031                 break;
6032         }
6033
6034         // TODO: thread this
6035         // NOTE: R_PrepareRTLights() also caches entities
6036
6037         for (i = 0;i < r_refdef.scene.numentities;i++)
6038                 if (r_refdef.viewcache.entityvisible[i])
6039                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
6040
6041         if (r_shadows.integer)
6042                 for (i = 0;i < r_refdef.scene.numentities;i++)
6043                         if (!r_refdef.viewcache.entityvisible[i])
6044                                 R_AnimCache_GetEntity(r_refdef.scene.entities[i], false, false);
6045 }
6046
6047 //==================================================================================
6048
6049 static void R_View_UpdateEntityLighting (void)
6050 {
6051         int i;
6052         entity_render_t *ent;
6053         vec3_t tempdiffusenormal, avg;
6054         vec_t f, fa, fd, fdd;
6055
6056         for (i = 0;i < r_refdef.scene.numentities;i++)
6057         {
6058                 ent = r_refdef.scene.entities[i];
6059
6060                 // skip unseen models
6061                 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
6062                         continue;
6063
6064                 // skip bsp models
6065                 if (ent->model && ent->model->brush.num_leafs)
6066                 {
6067                         // TODO: use modellight for r_ambient settings on world?
6068                         VectorSet(ent->modellight_ambient, 0, 0, 0);
6069                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
6070                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
6071                         continue;
6072                 }
6073
6074                 // fetch the lighting from the worldmodel data
6075                 VectorClear(ent->modellight_ambient);
6076                 VectorClear(ent->modellight_diffuse);
6077                 VectorClear(tempdiffusenormal);
6078                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
6079                 {
6080                         vec3_t org;
6081                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6082                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
6083                         if(ent->flags & RENDER_EQUALIZE)
6084                         {
6085                                 // first fix up ambient lighting...
6086                                 if(r_equalize_entities_minambient.value > 0)
6087                                 {
6088                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
6089                                         if(fd > 0)
6090                                         {
6091                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
6092                                                 if(fa < r_equalize_entities_minambient.value * fd)
6093                                                 {
6094                                                         // solve:
6095                                                         //   fa'/fd' = minambient
6096                                                         //   fa'+0.25*fd' = fa+0.25*fd
6097                                                         //   ...
6098                                                         //   fa' = fd' * minambient
6099                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
6100                                                         //   ...
6101                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
6102                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
6103                                                         //   ...
6104                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
6105                                                         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
6106                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
6107                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6108                                                 }
6109                                         }
6110                                 }
6111
6112                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
6113                                 {
6114                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
6115                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
6116                                         if(f > 0)
6117                                         {
6118                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
6119                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
6120                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6121                                         }
6122                                 }
6123                         }
6124                 }
6125                 else // highly rare
6126                         VectorSet(ent->modellight_ambient, 1, 1, 1);
6127
6128                 // move the light direction into modelspace coordinates for lighting code
6129                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
6130                 if(VectorLength2(ent->modellight_lightdir) == 0)
6131                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
6132                 VectorNormalize(ent->modellight_lightdir);
6133         }
6134 }
6135
6136 #define MAX_LINEOFSIGHTTRACES 64
6137
6138 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
6139 {
6140         int i;
6141         vec3_t boxmins, boxmaxs;
6142         vec3_t start;
6143         vec3_t end;
6144         dp_model_t *model = r_refdef.scene.worldmodel;
6145
6146         if (!model || !model->brush.TraceLineOfSight)
6147                 return true;
6148
6149         // expand the box a little
6150         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
6151         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
6152         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
6153         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
6154         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
6155         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
6156
6157         // try center
6158         VectorCopy(eye, start);
6159         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
6160         if (model->brush.TraceLineOfSight(model, start, end))
6161                 return true;
6162
6163         // try various random positions
6164         for (i = 0;i < numsamples;i++)
6165         {
6166                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
6167                 if (model->brush.TraceLineOfSight(model, start, end))
6168                         return true;
6169         }
6170
6171         return false;
6172 }
6173
6174
6175 static void R_View_UpdateEntityVisible (void)
6176 {
6177         int i;
6178         int renderimask;
6179         int samples;
6180         entity_render_t *ent;
6181
6182         renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
6183         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
6184         {
6185                 // worldmodel can check visibility
6186                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
6187                 for (i = 0;i < r_refdef.scene.numentities;i++)
6188                 {
6189                         ent = r_refdef.scene.entities[i];
6190                         if (!(ent->flags & renderimask))
6191                         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)))
6192                         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))
6193                                 r_refdef.viewcache.entityvisible[i] = true;
6194                 }
6195                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
6196                 {
6197                         for (i = 0;i < r_refdef.scene.numentities;i++)
6198                         {
6199                                 ent = r_refdef.scene.entities[i];
6200                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
6201                                 {
6202                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
6203                                         if (samples < 0)
6204                                                 continue; // temp entities do pvs only
6205                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
6206                                                 ent->last_trace_visibility = realtime;
6207                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
6208                                                 r_refdef.viewcache.entityvisible[i] = 0;
6209                                 }
6210                         }
6211                 }
6212         }
6213         else
6214         {
6215                 // no worldmodel or it can't check visibility
6216                 for (i = 0;i < r_refdef.scene.numentities;i++)
6217                 {
6218                         ent = r_refdef.scene.entities[i];
6219                         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));
6220                 }
6221         }
6222 }
6223
6224 /// only used if skyrendermasked, and normally returns false
6225 int R_DrawBrushModelsSky (void)
6226 {
6227         int i, sky;
6228         entity_render_t *ent;
6229
6230         sky = false;
6231         for (i = 0;i < r_refdef.scene.numentities;i++)
6232         {
6233                 if (!r_refdef.viewcache.entityvisible[i])
6234                         continue;
6235                 ent = r_refdef.scene.entities[i];
6236                 if (!ent->model || !ent->model->DrawSky)
6237                         continue;
6238                 ent->model->DrawSky(ent);
6239                 sky = true;
6240         }
6241         return sky;
6242 }
6243
6244 static void R_DrawNoModel(entity_render_t *ent);
6245 static void R_DrawModels(void)
6246 {
6247         int i;
6248         entity_render_t *ent;
6249
6250         for (i = 0;i < r_refdef.scene.numentities;i++)
6251         {
6252                 if (!r_refdef.viewcache.entityvisible[i])
6253                         continue;
6254                 ent = r_refdef.scene.entities[i];
6255                 r_refdef.stats.entities++;
6256                 if (ent->model && ent->model->Draw != NULL)
6257                         ent->model->Draw(ent);
6258                 else
6259                         R_DrawNoModel(ent);
6260         }
6261 }
6262
6263 static void R_DrawModelsDepth(void)
6264 {
6265         int i;
6266         entity_render_t *ent;
6267
6268         for (i = 0;i < r_refdef.scene.numentities;i++)
6269         {
6270                 if (!r_refdef.viewcache.entityvisible[i])
6271                         continue;
6272                 ent = r_refdef.scene.entities[i];
6273                 if (ent->model && ent->model->DrawDepth != NULL)
6274                         ent->model->DrawDepth(ent);
6275         }
6276 }
6277
6278 static void R_DrawModelsDebug(void)
6279 {
6280         int i;
6281         entity_render_t *ent;
6282
6283         for (i = 0;i < r_refdef.scene.numentities;i++)
6284         {
6285                 if (!r_refdef.viewcache.entityvisible[i])
6286                         continue;
6287                 ent = r_refdef.scene.entities[i];
6288                 if (ent->model && ent->model->DrawDebug != NULL)
6289                         ent->model->DrawDebug(ent);
6290         }
6291 }
6292
6293 static void R_DrawModelsAddWaterPlanes(void)
6294 {
6295         int i;
6296         entity_render_t *ent;
6297
6298         for (i = 0;i < r_refdef.scene.numentities;i++)
6299         {
6300                 if (!r_refdef.viewcache.entityvisible[i])
6301                         continue;
6302                 ent = r_refdef.scene.entities[i];
6303                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
6304                         ent->model->DrawAddWaterPlanes(ent);
6305         }
6306 }
6307
6308 static void R_View_SetFrustum(void)
6309 {
6310         int i;
6311         double slopex, slopey;
6312         vec3_t forward, left, up, origin;
6313
6314         // we can't trust r_refdef.view.forward and friends in reflected scenes
6315         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
6316
6317 #if 0
6318         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
6319         r_refdef.view.frustum[0].normal[1] = 0 - 0;
6320         r_refdef.view.frustum[0].normal[2] = -1 - 0;
6321         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
6322         r_refdef.view.frustum[1].normal[1] = 0 + 0;
6323         r_refdef.view.frustum[1].normal[2] = -1 + 0;
6324         r_refdef.view.frustum[2].normal[0] = 0 - 0;
6325         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
6326         r_refdef.view.frustum[2].normal[2] = -1 - 0;
6327         r_refdef.view.frustum[3].normal[0] = 0 + 0;
6328         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
6329         r_refdef.view.frustum[3].normal[2] = -1 + 0;
6330 #endif
6331
6332 #if 0
6333         zNear = r_refdef.nearclip;
6334         nudge = 1.0 - 1.0 / (1<<23);
6335         r_refdef.view.frustum[4].normal[0] = 0 - 0;
6336         r_refdef.view.frustum[4].normal[1] = 0 - 0;
6337         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
6338         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
6339         r_refdef.view.frustum[5].normal[0] = 0 + 0;
6340         r_refdef.view.frustum[5].normal[1] = 0 + 0;
6341         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
6342         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
6343 #endif
6344
6345
6346
6347 #if 0
6348         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
6349         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
6350         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
6351         r_refdef.view.frustum[0].dist = m[15] - m[12];
6352
6353         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
6354         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
6355         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
6356         r_refdef.view.frustum[1].dist = m[15] + m[12];
6357
6358         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
6359         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
6360         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
6361         r_refdef.view.frustum[2].dist = m[15] - m[13];
6362
6363         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
6364         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
6365         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
6366         r_refdef.view.frustum[3].dist = m[15] + m[13];
6367
6368         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
6369         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
6370         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
6371         r_refdef.view.frustum[4].dist = m[15] - m[14];
6372
6373         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
6374         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
6375         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
6376         r_refdef.view.frustum[5].dist = m[15] + m[14];
6377 #endif
6378
6379         if (r_refdef.view.useperspective)
6380         {
6381                 slopex = 1.0 / r_refdef.view.frustum_x;
6382                 slopey = 1.0 / r_refdef.view.frustum_y;
6383                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
6384                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
6385                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
6386                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
6387                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6388
6389                 // Leaving those out was a mistake, those were in the old code, and they
6390                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
6391                 // I couldn't reproduce it after adding those normalizations. --blub
6392                 VectorNormalize(r_refdef.view.frustum[0].normal);
6393                 VectorNormalize(r_refdef.view.frustum[1].normal);
6394                 VectorNormalize(r_refdef.view.frustum[2].normal);
6395                 VectorNormalize(r_refdef.view.frustum[3].normal);
6396
6397                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
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[0]);
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[1]);
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[2]);
6401                 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]);
6402
6403                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
6404                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
6405                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
6406                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
6407                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6408         }
6409         else
6410         {
6411                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
6412                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
6413                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
6414                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
6415                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6416                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
6417                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
6418                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
6419                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
6420                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6421         }
6422         r_refdef.view.numfrustumplanes = 5;
6423
6424         if (r_refdef.view.useclipplane)
6425         {
6426                 r_refdef.view.numfrustumplanes = 6;
6427                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
6428         }
6429
6430         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6431                 PlaneClassify(r_refdef.view.frustum + i);
6432
6433         // LordHavoc: note to all quake engine coders, Quake had a special case
6434         // for 90 degrees which assumed a square view (wrong), so I removed it,
6435         // Quake2 has it disabled as well.
6436
6437         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
6438         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
6439         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
6440         //PlaneClassify(&frustum[0]);
6441
6442         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
6443         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
6444         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
6445         //PlaneClassify(&frustum[1]);
6446
6447         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
6448         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
6449         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
6450         //PlaneClassify(&frustum[2]);
6451
6452         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
6453         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
6454         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
6455         //PlaneClassify(&frustum[3]);
6456
6457         // nearclip plane
6458         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
6459         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
6460         //PlaneClassify(&frustum[4]);
6461 }
6462
6463 void R_View_Update(void)
6464 {
6465         R_Main_ResizeViewCache();
6466         R_View_SetFrustum();
6467         R_View_WorldVisibility(r_refdef.view.useclipplane);
6468         R_View_UpdateEntityVisible();
6469         R_View_UpdateEntityLighting();
6470 }
6471
6472 void R_SetupView(qboolean allowwaterclippingplane)
6473 {
6474         const float *customclipplane = NULL;
6475         float plane[4];
6476         if (r_refdef.view.useclipplane && allowwaterclippingplane)
6477         {
6478                 // LordHavoc: couldn't figure out how to make this approach the
6479                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
6480                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
6481                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
6482                         dist = r_refdef.view.clipplane.dist;
6483                 plane[0] = r_refdef.view.clipplane.normal[0];
6484                 plane[1] = r_refdef.view.clipplane.normal[1];
6485                 plane[2] = r_refdef.view.clipplane.normal[2];
6486                 plane[3] = dist;
6487                 customclipplane = plane;
6488         }
6489
6490         if (!r_refdef.view.useperspective)
6491                 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);
6492         else if (vid.stencil && r_useinfinitefarclip.integer)
6493                 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);
6494         else
6495                 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);
6496         R_SetViewport(&r_refdef.view.viewport);
6497 }
6498
6499 void R_EntityMatrix(const matrix4x4_t *matrix)
6500 {
6501         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
6502         {
6503                 gl_modelmatrixchanged = false;
6504                 gl_modelmatrix = *matrix;
6505                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
6506                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
6507                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
6508                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
6509                 CHECKGLERROR
6510                 switch(vid.renderpath)
6511                 {
6512                 case RENDERPATH_GL20:
6513                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
6514                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6515                         break;
6516                 case RENDERPATH_CGGL:
6517 #ifdef SUPPORTCG
6518                         CHECKCGERROR
6519                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
6520                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6521 #endif
6522                         break;
6523                 case RENDERPATH_GL13:
6524                 case RENDERPATH_GL11:
6525                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6526                         break;
6527                 }
6528         }
6529 }
6530
6531 void R_ResetViewRendering2D(void)
6532 {
6533         r_viewport_t viewport;
6534         DrawQ_Finish();
6535
6536         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
6537         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);
6538         R_SetViewport(&viewport);
6539         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
6540         GL_Color(1, 1, 1, 1);
6541         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6542         GL_BlendFunc(GL_ONE, GL_ZERO);
6543         GL_AlphaTest(false);
6544         GL_ScissorTest(false);
6545         GL_DepthMask(false);
6546         GL_DepthRange(0, 1);
6547         GL_DepthTest(false);
6548         R_EntityMatrix(&identitymatrix);
6549         R_Mesh_ResetTextureState();
6550         GL_PolygonOffset(0, 0);
6551         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
6552         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6553         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
6554         qglStencilMask(~0);CHECKGLERROR
6555         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
6556         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
6557         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
6558 }
6559
6560 void R_ResetViewRendering3D(void)
6561 {
6562         DrawQ_Finish();
6563
6564         R_SetupView(true);
6565         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6566         GL_Color(1, 1, 1, 1);
6567         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6568         GL_BlendFunc(GL_ONE, GL_ZERO);
6569         GL_AlphaTest(false);
6570         GL_ScissorTest(true);
6571         GL_DepthMask(true);
6572         GL_DepthRange(0, 1);
6573         GL_DepthTest(true);
6574         R_EntityMatrix(&identitymatrix);
6575         R_Mesh_ResetTextureState();
6576         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6577         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
6578         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6579         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
6580         qglStencilMask(~0);CHECKGLERROR
6581         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
6582         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
6583         GL_CullFace(r_refdef.view.cullface_back);
6584 }
6585
6586 void R_RenderScene(void);
6587 void R_RenderWaterPlanes(void);
6588
6589 static void R_Water_StartFrame(void)
6590 {
6591         int i;
6592         int waterwidth, waterheight, texturewidth, textureheight;
6593         r_waterstate_waterplane_t *p;
6594
6595         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
6596                 return;
6597
6598         switch(vid.renderpath)
6599         {
6600         case RENDERPATH_GL20:
6601         case RENDERPATH_CGGL:
6602                 break;
6603         case RENDERPATH_GL13:
6604         case RENDERPATH_GL11:
6605                 return;
6606         }
6607
6608         // set waterwidth and waterheight to the water resolution that will be
6609         // used (often less than the screen resolution for faster rendering)
6610         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
6611         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
6612
6613         // calculate desired texture sizes
6614         // can't use water if the card does not support the texture size
6615         if (!r_water.integer || r_showsurfaces.integer)
6616                 texturewidth = textureheight = waterwidth = waterheight = 0;
6617         else if (vid.support.arb_texture_non_power_of_two)
6618         {
6619                 texturewidth = waterwidth;
6620                 textureheight = waterheight;
6621         }
6622         else
6623         {
6624                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
6625                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
6626         }
6627
6628         // allocate textures as needed
6629         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
6630         {
6631                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
6632                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
6633                 {
6634                         if (p->texture_refraction)
6635                                 R_FreeTexture(p->texture_refraction);
6636                         p->texture_refraction = NULL;
6637                         if (p->texture_reflection)
6638                                 R_FreeTexture(p->texture_reflection);
6639                         p->texture_reflection = NULL;
6640                 }
6641                 memset(&r_waterstate, 0, sizeof(r_waterstate));
6642                 r_waterstate.texturewidth = texturewidth;
6643                 r_waterstate.textureheight = textureheight;
6644         }
6645
6646         if (r_waterstate.texturewidth)
6647         {
6648                 r_waterstate.enabled = true;
6649
6650                 // when doing a reduced render (HDR) we want to use a smaller area
6651                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
6652                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
6653
6654                 // set up variables that will be used in shader setup
6655                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
6656                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
6657                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
6658                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
6659         }
6660
6661         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
6662         r_waterstate.numwaterplanes = 0;
6663 }
6664
6665 void R_Water_AddWaterPlane(msurface_t *surface)
6666 {
6667         int triangleindex, planeindex;
6668         const int *e;
6669         vec3_t vert[3];
6670         vec3_t normal;
6671         vec3_t center;
6672         mplane_t plane;
6673         r_waterstate_waterplane_t *p;
6674         texture_t *t = R_GetCurrentTexture(surface->texture);
6675         // just use the first triangle with a valid normal for any decisions
6676         VectorClear(normal);
6677         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
6678         {
6679                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
6680                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
6681                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
6682                 TriangleNormal(vert[0], vert[1], vert[2], normal);
6683                 if (VectorLength2(normal) >= 0.001)
6684                         break;
6685         }
6686
6687         VectorCopy(normal, plane.normal);
6688         VectorNormalize(plane.normal);
6689         plane.dist = DotProduct(vert[0], plane.normal);
6690         PlaneClassify(&plane);
6691         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
6692         {
6693                 // skip backfaces (except if nocullface is set)
6694                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
6695                         return;
6696                 VectorNegate(plane.normal, plane.normal);
6697                 plane.dist *= -1;
6698                 PlaneClassify(&plane);
6699         }
6700
6701
6702         // find a matching plane if there is one
6703         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6704                 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
6705                         break;
6706         if (planeindex >= r_waterstate.maxwaterplanes)
6707                 return; // nothing we can do, out of planes
6708
6709         // if this triangle does not fit any known plane rendered this frame, add one
6710         if (planeindex >= r_waterstate.numwaterplanes)
6711         {
6712                 // store the new plane
6713                 r_waterstate.numwaterplanes++;
6714                 p->plane = plane;
6715                 // clear materialflags and pvs
6716                 p->materialflags = 0;
6717                 p->pvsvalid = false;
6718         }
6719         // merge this surface's materialflags into the waterplane
6720         p->materialflags |= t->currentmaterialflags;
6721         // merge this surface's PVS into the waterplane
6722         VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
6723         if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6724          && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6725         {
6726                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6727                 p->pvsvalid = true;
6728         }
6729 }
6730
6731 static void R_Water_ProcessPlanes(void)
6732 {
6733         r_refdef_view_t originalview;
6734         r_refdef_view_t myview;
6735         int planeindex;
6736         r_waterstate_waterplane_t *p;
6737
6738         originalview = r_refdef.view;
6739
6740         // make sure enough textures are allocated
6741         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6742         {
6743                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6744                 {
6745                         if (!p->texture_refraction)
6746                                 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);
6747                         if (!p->texture_refraction)
6748                                 goto error;
6749                 }
6750
6751                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6752                 {
6753                         if (!p->texture_reflection)
6754                                 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);
6755                         if (!p->texture_reflection)
6756                                 goto error;
6757                 }
6758         }
6759
6760         // render views
6761         r_refdef.view = originalview;
6762         r_refdef.view.showdebug = false;
6763         r_refdef.view.width = r_waterstate.waterwidth;
6764         r_refdef.view.height = r_waterstate.waterheight;
6765         r_refdef.view.useclipplane = true;
6766         myview = r_refdef.view;
6767         r_waterstate.renderingscene = true;
6768         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6769         {
6770                 // render the normal view scene and copy into texture
6771                 // (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)
6772                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6773                 {
6774                         r_refdef.view = myview;
6775                         r_refdef.view.clipplane = p->plane;
6776                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6777                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6778                         PlaneClassify(&r_refdef.view.clipplane);
6779
6780                         R_ResetViewRendering3D();
6781                         R_ClearScreen(r_refdef.fogenabled);
6782                         R_View_Update();
6783                         R_RenderScene();
6784
6785                         R_Mesh_CopyToTexture(R_GetTexture(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);
6786                 }
6787
6788                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6789                 {
6790                         r_refdef.view = myview;
6791                         // render reflected scene and copy into texture
6792                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6793                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6794                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6795                         r_refdef.view.clipplane = p->plane;
6796                         // reverse the cullface settings for this render
6797                         r_refdef.view.cullface_front = GL_FRONT;
6798                         r_refdef.view.cullface_back = GL_BACK;
6799                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6800                         {
6801                                 r_refdef.view.usecustompvs = true;
6802                                 if (p->pvsvalid)
6803                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6804                                 else
6805                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6806                         }
6807
6808                         R_ResetViewRendering3D();
6809                         R_ClearScreen(r_refdef.fogenabled);
6810                         R_View_Update();
6811                         R_RenderScene();
6812
6813                         R_Mesh_CopyToTexture(R_GetTexture(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);
6814                 }
6815         }
6816         r_waterstate.renderingscene = false;
6817         r_refdef.view = originalview;
6818         R_ResetViewRendering3D();
6819         R_ClearScreen(r_refdef.fogenabled);
6820         R_View_Update();
6821         return;
6822 error:
6823         r_refdef.view = originalview;
6824         r_waterstate.renderingscene = false;
6825         Cvar_SetValueQuick(&r_water, 0);
6826         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6827         return;
6828 }
6829
6830 void R_Bloom_StartFrame(void)
6831 {
6832         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6833
6834         switch(vid.renderpath)
6835         {
6836         case RENDERPATH_GL20:
6837         case RENDERPATH_CGGL:
6838                 break;
6839         case RENDERPATH_GL13:
6840         case RENDERPATH_GL11:
6841                 return;
6842         }
6843
6844         // set bloomwidth and bloomheight to the bloom resolution that will be
6845         // used (often less than the screen resolution for faster rendering)
6846         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
6847         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
6848         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
6849         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
6850         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
6851
6852         // calculate desired texture sizes
6853         if (vid.support.arb_texture_non_power_of_two)
6854         {
6855                 screentexturewidth = r_refdef.view.width;
6856                 screentextureheight = r_refdef.view.height;
6857                 bloomtexturewidth = r_bloomstate.bloomwidth;
6858                 bloomtextureheight = r_bloomstate.bloomheight;
6859         }
6860         else
6861         {
6862                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
6863                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
6864                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
6865                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
6866         }
6867
6868         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))
6869         {
6870                 Cvar_SetValueQuick(&r_hdr, 0);
6871                 Cvar_SetValueQuick(&r_bloom, 0);
6872                 Cvar_SetValueQuick(&r_motionblur, 0);
6873                 Cvar_SetValueQuick(&r_damageblur, 0);
6874         }
6875
6876         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)))
6877                 screentexturewidth = screentextureheight = 0;
6878         if (!r_hdr.integer && !r_bloom.integer)
6879                 bloomtexturewidth = bloomtextureheight = 0;
6880
6881         // allocate textures as needed
6882         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
6883         {
6884                 if (r_bloomstate.texture_screen)
6885                         R_FreeTexture(r_bloomstate.texture_screen);
6886                 r_bloomstate.texture_screen = NULL;
6887                 r_bloomstate.screentexturewidth = screentexturewidth;
6888                 r_bloomstate.screentextureheight = screentextureheight;
6889                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
6890                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
6891         }
6892         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
6893         {
6894                 if (r_bloomstate.texture_bloom)
6895                         R_FreeTexture(r_bloomstate.texture_bloom);
6896                 r_bloomstate.texture_bloom = NULL;
6897                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6898                 r_bloomstate.bloomtextureheight = bloomtextureheight;
6899                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6900                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
6901         }
6902
6903         // when doing a reduced render (HDR) we want to use a smaller area
6904         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6905         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6906         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6907         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6908         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6909
6910         // set up a texcoord array for the full resolution screen image
6911         // (we have to keep this around to copy back during final render)
6912         r_bloomstate.screentexcoord2f[0] = 0;
6913         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
6914         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
6915         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
6916         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
6917         r_bloomstate.screentexcoord2f[5] = 0;
6918         r_bloomstate.screentexcoord2f[6] = 0;
6919         r_bloomstate.screentexcoord2f[7] = 0;
6920
6921         // set up a texcoord array for the reduced resolution bloom image
6922         // (which will be additive blended over the screen image)
6923         r_bloomstate.bloomtexcoord2f[0] = 0;
6924         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6925         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6926         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6927         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6928         r_bloomstate.bloomtexcoord2f[5] = 0;
6929         r_bloomstate.bloomtexcoord2f[6] = 0;
6930         r_bloomstate.bloomtexcoord2f[7] = 0;
6931
6932         if (r_hdr.integer || r_bloom.integer)
6933         {
6934                 r_bloomstate.enabled = true;
6935                 r_bloomstate.hdr = r_hdr.integer != 0;
6936         }
6937
6938         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);
6939 }
6940
6941 void R_Bloom_CopyBloomTexture(float colorscale)
6942 {
6943         r_refdef.stats.bloom++;
6944
6945         // scale down screen texture to the bloom texture size
6946         CHECKGLERROR
6947         R_SetViewport(&r_bloomstate.viewport);
6948         GL_BlendFunc(GL_ONE, GL_ZERO);
6949         GL_Color(colorscale, colorscale, colorscale, 1);
6950         // TODO: optimize with multitexture or GLSL
6951         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
6952         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6953         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
6954         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6955
6956         // we now have a bloom image in the framebuffer
6957         // copy it into the bloom image texture for later processing
6958         R_Mesh_CopyToTexture(R_GetTexture(r_bloomstate.texture_bloom), 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
6959         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6960 }
6961
6962 void R_Bloom_CopyHDRTexture(void)
6963 {
6964         R_Mesh_CopyToTexture(R_GetTexture(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);
6965         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6966 }
6967
6968 void R_Bloom_MakeTexture(void)
6969 {
6970         int x, range, dir;
6971         float xoffset, yoffset, r, brighten;
6972
6973         r_refdef.stats.bloom++;
6974
6975         R_ResetViewRendering2D();
6976         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
6977         R_Mesh_ColorPointer(NULL, 0, 0);
6978
6979         // we have a bloom image in the framebuffer
6980         CHECKGLERROR
6981         R_SetViewport(&r_bloomstate.viewport);
6982
6983         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6984         {
6985                 x *= 2;
6986                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6987                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6988                 GL_Color(r, r, r, 1);
6989                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6990                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
6991                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
6992                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6993
6994                 // copy the vertically blurred bloom view to a texture
6995                 GL_ActiveTexture(0);
6996                 CHECKGLERROR
6997                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
6998                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6999         }
7000
7001         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
7002         brighten = r_bloom_brighten.value;
7003         if (r_hdr.integer)
7004                 brighten *= r_hdr_range.value;
7005         brighten = sqrt(brighten);
7006         if(range >= 1)
7007                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
7008         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7009         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
7010
7011         for (dir = 0;dir < 2;dir++)
7012         {
7013                 // blend on at multiple vertical offsets to achieve a vertical blur
7014                 // TODO: do offset blends using GLSL
7015                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
7016                 GL_BlendFunc(GL_ONE, GL_ZERO);
7017                 for (x = -range;x <= range;x++)
7018                 {
7019                         if (!dir){xoffset = 0;yoffset = x;}
7020                         else {xoffset = x;yoffset = 0;}
7021                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
7022                         yoffset /= (float)r_bloomstate.bloomtextureheight;
7023                         // compute a texcoord array with the specified x and y offset
7024                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
7025                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7026                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7027                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7028                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7029                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
7030                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
7031                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
7032                         // this r value looks like a 'dot' particle, fading sharply to
7033                         // black at the edges
7034                         // (probably not realistic but looks good enough)
7035                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
7036                         //r = brighten/(range*2+1);
7037                         r = brighten / (range * 2 + 1);
7038                         if(range >= 1)
7039                                 r *= (1 - x*x/(float)(range*range));
7040                         GL_Color(r, r, r, 1);
7041                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7042                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7043                         GL_BlendFunc(GL_ONE, GL_ONE);
7044                 }
7045
7046                 // copy the vertically blurred bloom view to a texture
7047                 GL_ActiveTexture(0);
7048                 CHECKGLERROR
7049                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
7050                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7051         }
7052
7053         // apply subtract last
7054         // (just like it would be in a GLSL shader)
7055         if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
7056         {
7057                 GL_BlendFunc(GL_ONE, GL_ZERO);
7058                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7059                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7060                 GL_Color(1, 1, 1, 1);
7061                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7062                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7063
7064                 GL_BlendFunc(GL_ONE, GL_ONE);
7065                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
7066                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7067                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7068                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
7069                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7070                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7071                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
7072
7073                 // copy the darkened bloom view to a texture
7074                 R_Mesh_CopyToTexture(R_GetTexture(r_bloomstate.texture_bloom), 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
7075                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7076         }
7077 }
7078
7079 void R_HDR_RenderBloomTexture(void)
7080 {
7081         int oldwidth, oldheight;
7082         float oldcolorscale;
7083
7084         oldcolorscale = r_refdef.view.colorscale;
7085         oldwidth = r_refdef.view.width;
7086         oldheight = r_refdef.view.height;
7087         r_refdef.view.width = r_bloomstate.bloomwidth;
7088         r_refdef.view.height = r_bloomstate.bloomheight;
7089
7090         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
7091         // TODO: add exposure compensation features
7092         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
7093
7094         r_refdef.view.showdebug = false;
7095         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
7096
7097         R_ResetViewRendering3D();
7098
7099         R_ClearScreen(r_refdef.fogenabled);
7100         if (r_timereport_active)
7101                 R_TimeReport("HDRclear");
7102
7103         R_View_Update();
7104         if (r_timereport_active)
7105                 R_TimeReport("visibility");
7106
7107         // only do secondary renders with HDR if r_hdr is 2 or higher
7108         r_waterstate.numwaterplanes = 0;
7109         if (r_waterstate.enabled && r_hdr.integer >= 2)
7110                 R_RenderWaterPlanes();
7111
7112         r_refdef.view.showdebug = true;
7113         R_RenderScene();
7114         r_waterstate.numwaterplanes = 0;
7115
7116         R_ResetViewRendering2D();
7117
7118         R_Bloom_CopyHDRTexture();
7119         R_Bloom_MakeTexture();
7120
7121         // restore the view settings
7122         r_refdef.view.width = oldwidth;
7123         r_refdef.view.height = oldheight;
7124         r_refdef.view.colorscale = oldcolorscale;
7125         r_frame++; // used only by R_GetCurrentTexture
7126
7127         R_ResetViewRendering3D();
7128
7129         R_ClearScreen(r_refdef.fogenabled);
7130         if (r_timereport_active)
7131                 R_TimeReport("viewclear");
7132 }
7133
7134 static void R_BlendView(void)
7135 {
7136         unsigned int permutation;
7137         float uservecs[4][4];
7138
7139         switch (vid.renderpath)
7140         {
7141         case RENDERPATH_GL20:
7142         case RENDERPATH_CGGL:
7143                 permutation =
7144                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
7145                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
7146                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
7147                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
7148                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
7149
7150                 if (r_bloomstate.texture_screen)
7151                 {
7152                         // make sure the buffer is available
7153                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
7154
7155                         R_ResetViewRendering2D();
7156                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7157                         R_Mesh_ColorPointer(NULL, 0, 0);
7158
7159                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
7160                         {
7161                                 // declare variables
7162                                 float speed;
7163                                 static float avgspeed;
7164
7165                                 speed = VectorLength(cl.movement_velocity);
7166
7167                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
7168                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
7169
7170                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
7171                                 speed = bound(0, speed, 1);
7172                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
7173
7174                                 // calculate values into a standard alpha
7175                                 cl.motionbluralpha = 1 - exp(-
7176                                                 (
7177                                                  (r_motionblur.value * speed / 80)
7178                                                  +
7179                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
7180                                                 )
7181                                                 /
7182                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
7183                                            );
7184
7185                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
7186                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
7187                                 // apply the blur
7188                                 if (cl.motionbluralpha > 0)
7189                                 {
7190                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7191                                         GL_Color(1, 1, 1, cl.motionbluralpha);
7192                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7193                                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7194                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7195                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7196                                 }
7197                         }
7198
7199                         // copy view into the screen texture
7200                         R_Mesh_CopyToTexture(R_GetTexture(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);
7201                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7202                 }
7203                 else if (!r_bloomstate.texture_bloom)
7204                 {
7205                         // we may still have to do view tint...
7206                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7207                         {
7208                                 // apply a color tint to the whole view
7209                                 R_ResetViewRendering2D();
7210                                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7211                                 R_Mesh_ColorPointer(NULL, 0, 0);
7212                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7213                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7214                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7215                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7216                         }
7217                         break; // no screen processing, no bloom, skip it
7218                 }
7219
7220                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
7221                 {
7222                         // render simple bloom effect
7223                         // copy the screen and shrink it and darken it for the bloom process
7224                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
7225                         // make the bloom texture
7226                         R_Bloom_MakeTexture();
7227                 }
7228
7229 #if _MSC_VER >= 1400
7230 #define sscanf sscanf_s
7231 #endif
7232                 memset(uservecs, 0, sizeof(uservecs));
7233                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
7234                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
7235                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
7236                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
7237
7238                 R_ResetViewRendering2D();
7239                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7240                 R_Mesh_ColorPointer(NULL, 0, 0);
7241                 GL_Color(1, 1, 1, 1);
7242                 GL_BlendFunc(GL_ONE, GL_ZERO);
7243                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7244                 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7245
7246                 switch(vid.renderpath)
7247                 {
7248                 case RENDERPATH_GL20:
7249                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
7250                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , R_GetTexture(r_bloomstate.texture_screen));
7251                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , R_GetTexture(r_bloomstate.texture_bloom ));
7252                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps       ));
7253                         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]);
7254                         if (r_glsl_permutation->loc_ClientTime         >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime        , cl.time);
7255                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
7256                         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]);
7257                         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]);
7258                         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]);
7259                         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]);
7260                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
7261                         break;
7262                 case RENDERPATH_CGGL:
7263 #ifdef SUPPORTCG
7264                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
7265                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , R_GetTexture(r_bloomstate.texture_screen));CHECKCGERROR
7266                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , R_GetTexture(r_bloomstate.texture_bloom ));CHECKCGERROR
7267                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, R_GetTexture(r_texture_gammaramps       ));CHECKCGERROR
7268                         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
7269                         if (r_cg_permutation->fp_ClientTime        ) cgGLSetParameter1f(     r_cg_permutation->fp_ClientTime        , cl.time);CHECKCGERROR
7270                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
7271                         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
7272                         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
7273                         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
7274                         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
7275                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
7276 #endif
7277                         break;
7278                 default:
7279                         break;
7280                 }
7281                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7282                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7283                 break;
7284         case RENDERPATH_GL13:
7285         case RENDERPATH_GL11:
7286                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7287                 {
7288                         // apply a color tint to the whole view
7289                         R_ResetViewRendering2D();
7290                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7291                         R_Mesh_ColorPointer(NULL, 0, 0);
7292                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7293                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7294                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7295                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7296                 }
7297                 break;
7298         }
7299 }
7300
7301 matrix4x4_t r_waterscrollmatrix;
7302
7303 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
7304 {
7305         if (r_refdef.fog_density)
7306         {
7307                 r_refdef.fogcolor[0] = r_refdef.fog_red;
7308                 r_refdef.fogcolor[1] = r_refdef.fog_green;
7309                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7310
7311                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7312                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7313                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7314                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7315
7316                 {
7317                         vec3_t fogvec;
7318                         VectorCopy(r_refdef.fogcolor, fogvec);
7319                         //   color.rgb *= ContrastBoost * SceneBrightness;
7320                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7321                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7322                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7323                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7324                 }
7325         }
7326 }
7327
7328 void R_UpdateVariables(void)
7329 {
7330         R_Textures_Frame();
7331
7332         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7333
7334         r_refdef.farclip = r_farclip_base.value;
7335         if (r_refdef.scene.worldmodel)
7336                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7337         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7338
7339         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7340                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7341         r_refdef.polygonfactor = 0;
7342         r_refdef.polygonoffset = 0;
7343         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7344         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7345
7346         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7347         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7348         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
7349         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7350         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7351         if (r_showsurfaces.integer)
7352         {
7353                 r_refdef.scene.rtworld = false;
7354                 r_refdef.scene.rtworldshadows = false;
7355                 r_refdef.scene.rtdlight = false;
7356                 r_refdef.scene.rtdlightshadows = false;
7357                 r_refdef.lightmapintensity = 0;
7358         }
7359
7360         if (gamemode == GAME_NEHAHRA)
7361         {
7362                 if (gl_fogenable.integer)
7363                 {
7364                         r_refdef.oldgl_fogenable = true;
7365                         r_refdef.fog_density = gl_fogdensity.value;
7366                         r_refdef.fog_red = gl_fogred.value;
7367                         r_refdef.fog_green = gl_foggreen.value;
7368                         r_refdef.fog_blue = gl_fogblue.value;
7369                         r_refdef.fog_alpha = 1;
7370                         r_refdef.fog_start = 0;
7371                         r_refdef.fog_end = gl_skyclip.value;
7372                         r_refdef.fog_height = 1<<30;
7373                         r_refdef.fog_fadedepth = 128;
7374                 }
7375                 else if (r_refdef.oldgl_fogenable)
7376                 {
7377                         r_refdef.oldgl_fogenable = false;
7378                         r_refdef.fog_density = 0;
7379                         r_refdef.fog_red = 0;
7380                         r_refdef.fog_green = 0;
7381                         r_refdef.fog_blue = 0;
7382                         r_refdef.fog_alpha = 0;
7383                         r_refdef.fog_start = 0;
7384                         r_refdef.fog_end = 0;
7385                         r_refdef.fog_height = 1<<30;
7386                         r_refdef.fog_fadedepth = 128;
7387                 }
7388         }
7389
7390         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7391         r_refdef.fog_start = max(0, r_refdef.fog_start);
7392         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7393
7394         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
7395
7396         if (r_refdef.fog_density && r_drawfog.integer)
7397         {
7398                 r_refdef.fogenabled = true;
7399                 // this is the point where the fog reaches 0.9986 alpha, which we
7400                 // consider a good enough cutoff point for the texture
7401                 // (0.9986 * 256 == 255.6)
7402                 if (r_fog_exp2.integer)
7403                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7404                 else
7405                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7406                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7407                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7408                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7409                 // fog color was already set
7410                 // update the fog texture
7411                 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)
7412                         R_BuildFogTexture();
7413         }
7414         else
7415                 r_refdef.fogenabled = false;
7416
7417         switch(vid.renderpath)
7418         {
7419         case RENDERPATH_GL20:
7420         case RENDERPATH_CGGL:
7421                 if(v_glslgamma.integer && !vid_gammatables_trivial)
7422                 {
7423                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7424                         {
7425                                 // build GLSL gamma texture
7426 #define RAMPWIDTH 256
7427                                 unsigned short ramp[RAMPWIDTH * 3];
7428                                 unsigned char rampbgr[RAMPWIDTH][4];
7429                                 int i;
7430
7431                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7432
7433                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7434                                 for(i = 0; i < RAMPWIDTH; ++i)
7435                                 {
7436                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7437                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7438                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7439                                         rampbgr[i][3] = 0;
7440                                 }
7441                                 if (r_texture_gammaramps)
7442                                 {
7443                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
7444                                 }
7445                                 else
7446                                 {
7447                                         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);
7448                                 }
7449                         }
7450                 }
7451                 else
7452                 {
7453                         // remove GLSL gamma texture
7454                 }
7455                 break;
7456         case RENDERPATH_GL13:
7457         case RENDERPATH_GL11:
7458                 break;
7459         }
7460 }
7461
7462 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7463 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7464 /*
7465 ================
7466 R_SelectScene
7467 ================
7468 */
7469 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7470         if( scenetype != r_currentscenetype ) {
7471                 // store the old scenetype
7472                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7473                 r_currentscenetype = scenetype;
7474                 // move in the new scene
7475                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7476         }
7477 }
7478
7479 /*
7480 ================
7481 R_GetScenePointer
7482 ================
7483 */
7484 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7485 {
7486         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7487         if( scenetype == r_currentscenetype ) {
7488                 return &r_refdef.scene;
7489         } else {
7490                 return &r_scenes_store[ scenetype ];
7491         }
7492 }
7493
7494 /*
7495 ================
7496 R_RenderView
7497 ================
7498 */
7499 void R_RenderView(void)
7500 {
7501         if (r_timereport_active)
7502                 R_TimeReport("start");
7503         r_frame++; // used only by R_GetCurrentTexture
7504         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7505
7506         if (!r_drawentities.integer)
7507                 r_refdef.scene.numentities = 0;
7508
7509         R_AnimCache_ClearCache();
7510         R_FrameData_NewFrame();
7511
7512         if (r_refdef.view.isoverlay)
7513         {
7514                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7515                 GL_Clear( GL_DEPTH_BUFFER_BIT );
7516                 R_TimeReport("depthclear");
7517
7518                 r_refdef.view.showdebug = false;
7519
7520                 r_waterstate.enabled = false;
7521                 r_waterstate.numwaterplanes = 0;
7522
7523                 R_RenderScene();
7524
7525                 CHECKGLERROR
7526                 return;
7527         }
7528
7529         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
7530                 return; //Host_Error ("R_RenderView: NULL worldmodel");
7531
7532         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
7533
7534         // break apart the view matrix into vectors for various purposes
7535         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
7536         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
7537         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
7538         VectorNegate(r_refdef.view.left, r_refdef.view.right);
7539         // make an inverted copy of the view matrix for tracking sprites
7540         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
7541
7542         R_Shadow_UpdateWorldLightSelection();
7543
7544         R_Bloom_StartFrame();
7545         R_Water_StartFrame();
7546
7547         CHECKGLERROR
7548         if (r_timereport_active)
7549                 R_TimeReport("viewsetup");
7550
7551         R_ResetViewRendering3D();
7552
7553         if (r_refdef.view.clear || r_refdef.fogenabled)
7554         {
7555                 R_ClearScreen(r_refdef.fogenabled);
7556                 if (r_timereport_active)
7557                         R_TimeReport("viewclear");
7558         }
7559         r_refdef.view.clear = true;
7560
7561         // this produces a bloom texture to be used in R_BlendView() later
7562         if (r_hdr.integer && r_bloomstate.bloomwidth)
7563                 R_HDR_RenderBloomTexture();
7564
7565         r_refdef.view.showdebug = true;
7566
7567         R_View_Update();
7568         if (r_timereport_active)
7569                 R_TimeReport("visibility");
7570
7571         r_waterstate.numwaterplanes = 0;
7572         if (r_waterstate.enabled)
7573                 R_RenderWaterPlanes();
7574
7575         R_RenderScene();
7576         r_waterstate.numwaterplanes = 0;
7577
7578         R_BlendView();
7579         if (r_timereport_active)
7580                 R_TimeReport("blendview");
7581
7582         GL_Scissor(0, 0, vid.width, vid.height);
7583         GL_ScissorTest(false);
7584         CHECKGLERROR
7585 }
7586
7587 void R_RenderWaterPlanes(void)
7588 {
7589         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7590         {
7591                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7592                 if (r_timereport_active)
7593                         R_TimeReport("waterworld");
7594         }
7595
7596         // don't let sound skip if going slow
7597         if (r_refdef.scene.extraupdate)
7598                 S_ExtraUpdate ();
7599
7600         R_DrawModelsAddWaterPlanes();
7601         if (r_timereport_active)
7602                 R_TimeReport("watermodels");
7603
7604         if (r_waterstate.numwaterplanes)
7605         {
7606                 R_Water_ProcessPlanes();
7607                 if (r_timereport_active)
7608                         R_TimeReport("waterscenes");
7609         }
7610 }
7611
7612 extern void R_DrawLightningBeams (void);
7613 extern void VM_CL_AddPolygonsToMeshQueue (void);
7614 extern void R_DrawPortals (void);
7615 extern cvar_t cl_locs_show;
7616 static void R_DrawLocs(void);
7617 static void R_DrawEntityBBoxes(void);
7618 static void R_DrawModelDecals(void);
7619 extern cvar_t cl_decals_newsystem;
7620 extern qboolean r_shadow_usingdeferredprepass;
7621 void R_RenderScene(void)
7622 {
7623         r_refdef.stats.renders++;
7624
7625         R_UpdateFogColor();
7626
7627         // don't let sound skip if going slow
7628         if (r_refdef.scene.extraupdate)
7629                 S_ExtraUpdate ();
7630
7631         R_MeshQueue_BeginScene();
7632
7633         R_SkyStartFrame();
7634
7635         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);
7636
7637         if (cl.csqc_vidvars.drawworld)
7638         {
7639                 // don't let sound skip if going slow
7640                 if (r_refdef.scene.extraupdate)
7641                         S_ExtraUpdate ();
7642
7643                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7644                 {
7645                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7646                         if (r_timereport_active)
7647                                 R_TimeReport("worldsky");
7648                 }
7649
7650                 if (R_DrawBrushModelsSky() && r_timereport_active)
7651                         R_TimeReport("bmodelsky");
7652
7653                 if (skyrendermasked && skyrenderlater)
7654                 {
7655                         // we have to force off the water clipping plane while rendering sky
7656                         R_SetupView(false);
7657                         R_Sky();
7658                         R_SetupView(true);
7659                         if (r_timereport_active)
7660                                 R_TimeReport("sky");
7661                 }
7662         }
7663
7664         R_AnimCache_CacheVisibleEntities();
7665         if (r_timereport_active)
7666                 R_TimeReport("animation");
7667
7668         R_Shadow_PrepareLights();
7669         if (r_timereport_active)
7670                 R_TimeReport("preparelights");
7671
7672         if (r_shadow_usingdeferredprepass)
7673                 R_Shadow_DrawPrepass();
7674
7675         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7676         {
7677                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7678                 if (r_timereport_active)
7679                         R_TimeReport("worlddepth");
7680         }
7681         if (r_depthfirst.integer >= 2)
7682         {
7683                 R_DrawModelsDepth();
7684                 if (r_timereport_active)
7685                         R_TimeReport("modeldepth");
7686         }
7687
7688         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7689         {
7690                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7691                 if (r_timereport_active)
7692                         R_TimeReport("world");
7693         }
7694
7695         // don't let sound skip if going slow
7696         if (r_refdef.scene.extraupdate)
7697                 S_ExtraUpdate ();
7698
7699         R_DrawModels();
7700         if (r_timereport_active)
7701                 R_TimeReport("models");
7702
7703         // don't let sound skip if going slow
7704         if (r_refdef.scene.extraupdate)
7705                 S_ExtraUpdate ();
7706
7707         if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7708         {
7709                 R_DrawModelShadows();
7710                 R_ResetViewRendering3D();
7711                 // don't let sound skip if going slow
7712                 if (r_refdef.scene.extraupdate)
7713                         S_ExtraUpdate ();
7714         }
7715
7716         if (!r_shadow_usingdeferredprepass)
7717         {
7718                 R_Shadow_DrawLights();
7719                 if (r_timereport_active)
7720                         R_TimeReport("rtlights");
7721         }
7722
7723         // don't let sound skip if going slow
7724         if (r_refdef.scene.extraupdate)
7725                 S_ExtraUpdate ();
7726
7727         if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7728         {
7729                 R_DrawModelShadows();
7730                 R_ResetViewRendering3D();
7731                 // don't let sound skip if going slow
7732                 if (r_refdef.scene.extraupdate)
7733                         S_ExtraUpdate ();
7734         }
7735
7736         if (cl.csqc_vidvars.drawworld)
7737         {
7738                 if (cl_decals_newsystem.integer)
7739                 {
7740                         R_DrawModelDecals();
7741                         if (r_timereport_active)
7742                                 R_TimeReport("modeldecals");
7743                 }
7744                 else
7745                 {
7746                         R_DrawDecals();
7747                         if (r_timereport_active)
7748                                 R_TimeReport("decals");
7749                 }
7750
7751                 R_DrawParticles();
7752                 if (r_timereport_active)
7753                         R_TimeReport("particles");
7754
7755                 R_DrawExplosions();
7756                 if (r_timereport_active)
7757                         R_TimeReport("explosions");
7758
7759                 R_DrawLightningBeams();
7760                 if (r_timereport_active)
7761                         R_TimeReport("lightning");
7762         }
7763
7764         VM_CL_AddPolygonsToMeshQueue();
7765
7766         if (r_refdef.view.showdebug)
7767         {
7768                 if (cl_locs_show.integer)
7769                 {
7770                         R_DrawLocs();
7771                         if (r_timereport_active)
7772                                 R_TimeReport("showlocs");
7773                 }
7774
7775                 if (r_drawportals.integer)
7776                 {
7777                         R_DrawPortals();
7778                         if (r_timereport_active)
7779                                 R_TimeReport("portals");
7780                 }
7781
7782                 if (r_showbboxes.value > 0)
7783                 {
7784                         R_DrawEntityBBoxes();
7785                         if (r_timereport_active)
7786                                 R_TimeReport("bboxes");
7787                 }
7788         }
7789
7790         R_MeshQueue_RenderTransparent();
7791         if (r_timereport_active)
7792                 R_TimeReport("drawtrans");
7793
7794         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))
7795         {
7796                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7797                 if (r_timereport_active)
7798                         R_TimeReport("worlddebug");
7799                 R_DrawModelsDebug();
7800                 if (r_timereport_active)
7801                         R_TimeReport("modeldebug");
7802         }
7803
7804         if (cl.csqc_vidvars.drawworld)
7805         {
7806                 R_Shadow_DrawCoronas();
7807                 if (r_timereport_active)
7808                         R_TimeReport("coronas");
7809         }
7810
7811         // don't let sound skip if going slow
7812         if (r_refdef.scene.extraupdate)
7813                 S_ExtraUpdate ();
7814
7815         R_ResetViewRendering2D();
7816 }
7817
7818 static const unsigned short bboxelements[36] =
7819 {
7820         5, 1, 3, 5, 3, 7,
7821         6, 2, 0, 6, 0, 4,
7822         7, 3, 2, 7, 2, 6,
7823         4, 0, 1, 4, 1, 5,
7824         4, 5, 7, 4, 7, 6,
7825         1, 0, 2, 1, 2, 3,
7826 };
7827
7828 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7829 {
7830         int i;
7831         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7832
7833         RSurf_ActiveWorldEntity();
7834
7835         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7836         GL_DepthMask(false);
7837         GL_DepthRange(0, 1);
7838         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7839         R_Mesh_ResetTextureState();
7840
7841         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7842         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7843         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7844         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7845         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7846         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7847         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7848         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7849         R_FillColors(color4f, 8, cr, cg, cb, ca);
7850         if (r_refdef.fogenabled)
7851         {
7852                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7853                 {
7854                         f1 = RSurf_FogVertex(v);
7855                         f2 = 1 - f1;
7856                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7857                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7858                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7859                 }
7860         }
7861         R_Mesh_VertexPointer(vertex3f, 0, 0);
7862         R_Mesh_ColorPointer(color4f, 0, 0);
7863         R_Mesh_ResetTextureState();
7864         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7865         R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
7866 }
7867
7868 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7869 {
7870         int i;
7871         float color[4];
7872         prvm_edict_t *edict;
7873         prvm_prog_t *prog_save = prog;
7874
7875         // this function draws bounding boxes of server entities
7876         if (!sv.active)
7877                 return;
7878
7879         GL_CullFace(GL_NONE);
7880         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7881
7882         prog = 0;
7883         SV_VM_Begin();
7884         for (i = 0;i < numsurfaces;i++)
7885         {
7886                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7887                 switch ((int)edict->fields.server->solid)
7888                 {
7889                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7890                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7891                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7892                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7893                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7894                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7895                 }
7896                 color[3] *= r_showbboxes.value;
7897                 color[3] = bound(0, color[3], 1);
7898                 GL_DepthTest(!r_showdisabledepthtest.integer);
7899                 GL_CullFace(r_refdef.view.cullface_front);
7900                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7901         }
7902         SV_VM_End();
7903         prog = prog_save;
7904 }
7905
7906 static void R_DrawEntityBBoxes(void)
7907 {
7908         int i;
7909         prvm_edict_t *edict;
7910         vec3_t center;
7911         prvm_prog_t *prog_save = prog;
7912
7913         // this function draws bounding boxes of server entities
7914         if (!sv.active)
7915                 return;
7916
7917         prog = 0;
7918         SV_VM_Begin();
7919         for (i = 0;i < prog->num_edicts;i++)
7920         {
7921                 edict = PRVM_EDICT_NUM(i);
7922                 if (edict->priv.server->free)
7923                         continue;
7924                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7925                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
7926                         continue;
7927                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
7928                         continue;
7929                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7930                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7931         }
7932         SV_VM_End();
7933         prog = prog_save;
7934 }
7935
7936 static const int nomodelelement3i[24] =
7937 {
7938         5, 2, 0,
7939         5, 1, 2,
7940         5, 0, 3,
7941         5, 3, 1,
7942         0, 2, 4,
7943         2, 1, 4,
7944         3, 0, 4,
7945         1, 3, 4
7946 };
7947
7948 static const unsigned short nomodelelement3s[24] =
7949 {
7950         5, 2, 0,
7951         5, 1, 2,
7952         5, 0, 3,
7953         5, 3, 1,
7954         0, 2, 4,
7955         2, 1, 4,
7956         3, 0, 4,
7957         1, 3, 4
7958 };
7959
7960 static const float nomodelvertex3f[6*3] =
7961 {
7962         -16,   0,   0,
7963          16,   0,   0,
7964           0, -16,   0,
7965           0,  16,   0,
7966           0,   0, -16,
7967           0,   0,  16
7968 };
7969
7970 static const float nomodelcolor4f[6*4] =
7971 {
7972         0.0f, 0.0f, 0.5f, 1.0f,
7973         0.0f, 0.0f, 0.5f, 1.0f,
7974         0.0f, 0.5f, 0.0f, 1.0f,
7975         0.0f, 0.5f, 0.0f, 1.0f,
7976         0.5f, 0.0f, 0.0f, 1.0f,
7977         0.5f, 0.0f, 0.0f, 1.0f
7978 };
7979
7980 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7981 {
7982         int i;
7983         float f1, f2, *c;
7984         float color4f[6*4];
7985
7986         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);
7987
7988         // this is only called once per entity so numsurfaces is always 1, and
7989         // surfacelist is always {0}, so this code does not handle batches
7990
7991         if (rsurface.ent_flags & RENDER_ADDITIVE)
7992         {
7993                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7994                 GL_DepthMask(false);
7995         }
7996         else if (rsurface.colormod[3] < 1)
7997         {
7998                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7999                 GL_DepthMask(false);
8000         }
8001         else
8002         {
8003                 GL_BlendFunc(GL_ONE, GL_ZERO);
8004                 GL_DepthMask(true);
8005         }
8006         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8007         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8008         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8009         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8010         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8011         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
8012         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8013         R_Mesh_ColorPointer(color4f, 0, 0);
8014         for (i = 0, c = color4f;i < 6;i++, c += 4)
8015         {
8016                 c[0] *= rsurface.colormod[0];
8017                 c[1] *= rsurface.colormod[1];
8018                 c[2] *= rsurface.colormod[2];
8019                 c[3] *= rsurface.colormod[3];
8020         }
8021         if (r_refdef.fogenabled)
8022         {
8023                 for (i = 0, c = color4f;i < 6;i++, c += 4)
8024                 {
8025                         f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
8026                         f2 = 1 - f1;
8027                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8028                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8029                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8030                 }
8031         }
8032         R_Mesh_ResetTextureState();
8033         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
8034 }
8035
8036 void R_DrawNoModel(entity_render_t *ent)
8037 {
8038         vec3_t org;
8039         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8040         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8041                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8042         else
8043                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8044 }
8045
8046 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8047 {
8048         vec3_t right1, right2, diff, normal;
8049
8050         VectorSubtract (org2, org1, normal);
8051
8052         // calculate 'right' vector for start
8053         VectorSubtract (r_refdef.view.origin, org1, diff);
8054         CrossProduct (normal, diff, right1);
8055         VectorNormalize (right1);
8056
8057         // calculate 'right' vector for end
8058         VectorSubtract (r_refdef.view.origin, org2, diff);
8059         CrossProduct (normal, diff, right2);
8060         VectorNormalize (right2);
8061
8062         vert[ 0] = org1[0] + width * right1[0];
8063         vert[ 1] = org1[1] + width * right1[1];
8064         vert[ 2] = org1[2] + width * right1[2];
8065         vert[ 3] = org1[0] - width * right1[0];
8066         vert[ 4] = org1[1] - width * right1[1];
8067         vert[ 5] = org1[2] - width * right1[2];
8068         vert[ 6] = org2[0] - width * right2[0];
8069         vert[ 7] = org2[1] - width * right2[1];
8070         vert[ 8] = org2[2] - width * right2[2];
8071         vert[ 9] = org2[0] + width * right2[0];
8072         vert[10] = org2[1] + width * right2[1];
8073         vert[11] = org2[2] + width * right2[2];
8074 }
8075
8076 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)
8077 {
8078         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8079         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8080         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8081         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8082         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8083         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8084         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8085         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8086         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8087         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8088         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8089         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8090 }
8091
8092 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8093 {
8094         int i;
8095         float *vertex3f;
8096         float v[3];
8097         VectorSet(v, x, y, z);
8098         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8099                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8100                         break;
8101         if (i == mesh->numvertices)
8102         {
8103                 if (mesh->numvertices < mesh->maxvertices)
8104                 {
8105                         VectorCopy(v, vertex3f);
8106                         mesh->numvertices++;
8107                 }
8108                 return mesh->numvertices;
8109         }
8110         else
8111                 return i;
8112 }
8113
8114 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8115 {
8116         int i;
8117         int *e, element[3];
8118         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8119         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8120         e = mesh->element3i + mesh->numtriangles * 3;
8121         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8122         {
8123                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8124                 if (mesh->numtriangles < mesh->maxtriangles)
8125                 {
8126                         *e++ = element[0];
8127                         *e++ = element[1];
8128                         *e++ = element[2];
8129                         mesh->numtriangles++;
8130                 }
8131                 element[1] = element[2];
8132         }
8133 }
8134
8135 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8136 {
8137         int i;
8138         int *e, element[3];
8139         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8140         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8141         e = mesh->element3i + mesh->numtriangles * 3;
8142         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8143         {
8144                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8145                 if (mesh->numtriangles < mesh->maxtriangles)
8146                 {
8147                         *e++ = element[0];
8148                         *e++ = element[1];
8149                         *e++ = element[2];
8150                         mesh->numtriangles++;
8151                 }
8152                 element[1] = element[2];
8153         }
8154 }
8155
8156 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8157 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8158 {
8159         int planenum, planenum2;
8160         int w;
8161         int tempnumpoints;
8162         mplane_t *plane, *plane2;
8163         double maxdist;
8164         double temppoints[2][256*3];
8165         // figure out how large a bounding box we need to properly compute this brush
8166         maxdist = 0;
8167         for (w = 0;w < numplanes;w++)
8168                 maxdist = max(maxdist, fabs(planes[w].dist));
8169         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8170         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8171         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8172         {
8173                 w = 0;
8174                 tempnumpoints = 4;
8175                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8176                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8177                 {
8178                         if (planenum2 == planenum)
8179                                 continue;
8180                         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);
8181                         w = !w;
8182                 }
8183                 if (tempnumpoints < 3)
8184                         continue;
8185                 // generate elements forming a triangle fan for this polygon
8186                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8187         }
8188 }
8189
8190 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)
8191 {
8192         texturelayer_t *layer;
8193         layer = t->currentlayers + t->currentnumlayers++;
8194         layer->type = type;
8195         layer->depthmask = depthmask;
8196         layer->blendfunc1 = blendfunc1;
8197         layer->blendfunc2 = blendfunc2;
8198         layer->texture = texture;
8199         layer->texmatrix = *matrix;
8200         layer->color[0] = r;
8201         layer->color[1] = g;
8202         layer->color[2] = b;
8203         layer->color[3] = a;
8204 }
8205
8206 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8207 {
8208         double index, f;
8209         index = parms[2] + r_refdef.scene.time * parms[3];
8210         index -= floor(index);
8211         switch (func)
8212         {
8213         default:
8214         case Q3WAVEFUNC_NONE:
8215         case Q3WAVEFUNC_NOISE:
8216         case Q3WAVEFUNC_COUNT:
8217                 f = 0;
8218                 break;
8219         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8220         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8221         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8222         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8223         case Q3WAVEFUNC_TRIANGLE:
8224                 index *= 4;
8225                 f = index - floor(index);
8226                 if (index < 1)
8227                         f = f;
8228                 else if (index < 2)
8229                         f = 1 - f;
8230                 else if (index < 3)
8231                         f = -f;
8232                 else
8233                         f = -(1 - f);
8234                 break;
8235         }
8236         return (float)(parms[0] + parms[1] * f);
8237 }
8238
8239 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8240 {
8241         int w, h, idx;
8242         float f;
8243         float tcmat[12];
8244         matrix4x4_t matrix, temp;
8245         switch(tcmod->tcmod)
8246         {
8247                 case Q3TCMOD_COUNT:
8248                 case Q3TCMOD_NONE:
8249                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8250                                 matrix = r_waterscrollmatrix;
8251                         else
8252                                 matrix = identitymatrix;
8253                         break;
8254                 case Q3TCMOD_ENTITYTRANSLATE:
8255                         // this is used in Q3 to allow the gamecode to control texcoord
8256                         // scrolling on the entity, which is not supported in darkplaces yet.
8257                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8258                         break;
8259                 case Q3TCMOD_ROTATE:
8260                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8261                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
8262                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8263                         break;
8264                 case Q3TCMOD_SCALE:
8265                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8266                         break;
8267                 case Q3TCMOD_SCROLL:
8268                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
8269                         break;
8270                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8271                         w = (int) tcmod->parms[0];
8272                         h = (int) tcmod->parms[1];
8273                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
8274                         f = f - floor(f);
8275                         idx = (int) floor(f * w * h);
8276                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8277                         break;
8278                 case Q3TCMOD_STRETCH:
8279                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8280                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8281                         break;
8282                 case Q3TCMOD_TRANSFORM:
8283                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8284                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8285                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8286                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8287                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8288                         break;
8289                 case Q3TCMOD_TURBULENT:
8290                         // this is handled in the RSurf_PrepareVertices function
8291                         matrix = identitymatrix;
8292                         break;
8293         }
8294         temp = *texmatrix;
8295         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8296 }
8297
8298 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8299 {
8300         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
8301         char name[MAX_QPATH];
8302         skinframe_t *skinframe;
8303         unsigned char pixels[296*194];
8304         strlcpy(cache->name, skinname, sizeof(cache->name));
8305         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8306         if (developer_loading.integer)
8307                 Con_Printf("loading %s\n", name);
8308         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8309         if (!skinframe || !skinframe->base)
8310         {
8311                 unsigned char *f;
8312                 fs_offset_t filesize;
8313                 skinframe = NULL;
8314                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8315                 if (f)
8316                 {
8317                         if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
8318                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8319                         Mem_Free(f);
8320                 }
8321         }
8322         cache->skinframe = skinframe;
8323 }
8324
8325 texture_t *R_GetCurrentTexture(texture_t *t)
8326 {
8327         int i;
8328         const entity_render_t *ent = rsurface.entity;
8329         dp_model_t *model = ent->model;
8330         q3shaderinfo_layer_tcmod_t *tcmod;
8331
8332         if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
8333                 return t->currentframe;
8334         t->update_lastrenderframe = r_frame;
8335         t->update_lastrenderentity = (void *)ent;
8336
8337         // switch to an alternate material if this is a q1bsp animated material
8338         {
8339                 texture_t *texture = t;
8340                 int s = rsurface.ent_skinnum;
8341                 if ((unsigned int)s >= (unsigned int)model->numskins)
8342                         s = 0;
8343                 if (model->skinscenes)
8344                 {
8345                         if (model->skinscenes[s].framecount > 1)
8346                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8347                         else
8348                                 s = model->skinscenes[s].firstframe;
8349                 }
8350                 if (s > 0)
8351                         t = t + s * model->num_surfaces;
8352                 if (t->animated)
8353                 {
8354                         // use an alternate animation if the entity's frame is not 0,
8355                         // and only if the texture has an alternate animation
8356                         if (rsurface.ent_alttextures && t->anim_total[1])
8357                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
8358                         else
8359                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
8360                 }
8361                 texture->currentframe = t;
8362         }
8363
8364         // update currentskinframe to be a qw skin or animation frame
8365         if (rsurface.ent_qwskin >= 0)
8366         {
8367                 i = rsurface.ent_qwskin;
8368                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8369                 {
8370                         r_qwskincache_size = cl.maxclients;
8371                         if (r_qwskincache)
8372                                 Mem_Free(r_qwskincache);
8373                         r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8374                 }
8375                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8376                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8377                 t->currentskinframe = r_qwskincache[i].skinframe;
8378                 if (t->currentskinframe == NULL)
8379                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8380         }
8381         else if (t->numskinframes >= 2)
8382                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8383         if (t->backgroundnumskinframes >= 2)
8384                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
8385
8386         t->currentmaterialflags = t->basematerialflags;
8387         t->currentalpha = rsurface.colormod[3];
8388         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
8389                 t->currentalpha *= r_wateralpha.value;
8390         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
8391                 t->currentalpha *= t->r_water_wateralpha;
8392         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
8393                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
8394         if (!(rsurface.ent_flags & RENDER_LIGHT))
8395                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8396         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8397         {
8398                 // pick a model lighting mode
8399                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8400                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8401                 else
8402                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8403         }
8404         if (rsurface.ent_flags & RENDER_ADDITIVE)
8405                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8406         else if (t->currentalpha < 1)
8407                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8408         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8409                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8410         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8411                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8412         if (t->backgroundnumskinframes)
8413                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8414         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8415         {
8416                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
8417                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8418         }
8419         else
8420                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
8421         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8422                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8423
8424         // there is no tcmod
8425         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8426         {
8427                 t->currenttexmatrix = r_waterscrollmatrix;
8428                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8429         }
8430         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8431         {
8432                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8433                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8434         }
8435
8436         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8437                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8438         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8439                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8440
8441         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8442         if (t->currentskinframe->qpixels)
8443                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8444         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8445         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8446         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8447         t->nmaptexture = t->currentskinframe->nmap;
8448         t->glosstexture = r_texture_black;
8449         t->glowtexture = t->currentskinframe->glow;
8450         t->fogtexture = t->currentskinframe->fog;
8451         if (t->backgroundnumskinframes)
8452         {
8453                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8454                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8455                 t->backgroundglosstexture = r_texture_black;
8456                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8457         }
8458         else
8459         {
8460                 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
8461                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8462                 t->backgroundglosstexture = r_texture_black;
8463                 t->backgroundglowtexture = NULL;
8464         }
8465         t->specularpower = r_shadow_glossexponent.value;
8466         // TODO: store reference values for these in the texture?
8467         t->specularscale = 0;
8468         if (r_shadow_gloss.integer > 0)
8469         {
8470                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8471                 {
8472                         if (r_shadow_glossintensity.value > 0)
8473                         {
8474                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8475                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8476                                 t->specularscale = r_shadow_glossintensity.value;
8477                         }
8478                 }
8479                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8480                 {
8481                         t->glosstexture = r_texture_white;
8482                         t->backgroundglosstexture = r_texture_white;
8483                         t->specularscale = r_shadow_gloss2intensity.value;
8484                         t->specularpower = r_shadow_gloss2exponent.value;
8485                 }
8486         }
8487         t->specularscale *= t->specularscalemod;
8488         t->specularpower *= t->specularpowermod;
8489
8490         // lightmaps mode looks bad with dlights using actual texturing, so turn
8491         // off the colormap and glossmap, but leave the normalmap on as it still
8492         // accurately represents the shading involved
8493         if (gl_lightmaps.integer)
8494         {
8495                 t->basetexture = r_texture_grey128;
8496                 t->pantstexture = r_texture_black;
8497                 t->shirttexture = r_texture_black;
8498                 t->nmaptexture = r_texture_blanknormalmap;
8499                 t->glosstexture = r_texture_black;
8500                 t->glowtexture = NULL;
8501                 t->fogtexture = NULL;
8502                 t->backgroundbasetexture = NULL;
8503                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8504                 t->backgroundglosstexture = r_texture_black;
8505                 t->backgroundglowtexture = NULL;
8506                 t->specularscale = 0;
8507                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8508         }
8509
8510         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8511         VectorClear(t->dlightcolor);
8512         t->currentnumlayers = 0;
8513         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8514         {
8515                 int blendfunc1, blendfunc2;
8516                 qboolean depthmask;
8517                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8518                 {
8519                         blendfunc1 = GL_SRC_ALPHA;
8520                         blendfunc2 = GL_ONE;
8521                 }
8522                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8523                 {
8524                         blendfunc1 = GL_SRC_ALPHA;
8525                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8526                 }
8527                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8528                 {
8529                         blendfunc1 = t->customblendfunc[0];
8530                         blendfunc2 = t->customblendfunc[1];
8531                 }
8532                 else
8533                 {
8534                         blendfunc1 = GL_ONE;
8535                         blendfunc2 = GL_ZERO;
8536                 }
8537                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8538                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8539                 {
8540                         // fullbright is not affected by r_refdef.lightmapintensity
8541                         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]);
8542                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8543                                 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]);
8544                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8545                                 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]);
8546                 }
8547                 else
8548                 {
8549                         vec3_t ambientcolor;
8550                         float colorscale;
8551                         // set the color tint used for lights affecting this surface
8552                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8553                         colorscale = 2;
8554                         // q3bsp has no lightmap updates, so the lightstylevalue that
8555                         // would normally be baked into the lightmap must be
8556                         // applied to the color
8557                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8558                         if (model->type == mod_brushq3)
8559                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8560                         colorscale *= r_refdef.lightmapintensity;
8561                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8562                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8563                         // basic lit geometry
8564                         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]);
8565                         // add pants/shirt if needed
8566                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8567                                 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]);
8568                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8569                                 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]);
8570                         // now add ambient passes if needed
8571                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8572                         {
8573                                 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]);
8574                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8575                                         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]);
8576                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8577                                         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]);
8578                         }
8579                 }
8580                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8581                         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]);
8582                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8583                 {
8584                         // if this is opaque use alpha blend which will darken the earlier
8585                         // passes cheaply.
8586                         //
8587                         // if this is an alpha blended material, all the earlier passes
8588                         // were darkened by fog already, so we only need to add the fog
8589                         // color ontop through the fog mask texture
8590                         //
8591                         // if this is an additive blended material, all the earlier passes
8592                         // were darkened by fog already, and we should not add fog color
8593                         // (because the background was not darkened, there is no fog color
8594                         // that was lost behind it).
8595                         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]);
8596                 }
8597         }
8598
8599         return t->currentframe;
8600 }
8601
8602 rsurfacestate_t rsurface;
8603
8604 void R_Mesh_ResizeArrays(int newvertices)
8605 {
8606         float *base;
8607         if (rsurface.array_size >= newvertices)
8608                 return;
8609         if (rsurface.array_modelvertex3f)
8610                 Mem_Free(rsurface.array_modelvertex3f);
8611         rsurface.array_size = (newvertices + 1023) & ~1023;
8612         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
8613         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
8614         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
8615         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
8616         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
8617         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
8618         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
8619         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
8620         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
8621         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
8622         rsurface.array_color4f           = base + rsurface.array_size * 27;
8623         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
8624 }
8625
8626 void RSurf_ActiveWorldEntity(void)
8627 {
8628         dp_model_t *model = r_refdef.scene.worldmodel;
8629         //if (rsurface.entity == r_refdef.scene.worldentity)
8630         //      return;
8631         rsurface.entity = r_refdef.scene.worldentity;
8632         rsurface.skeleton = NULL;
8633         rsurface.ent_skinnum = 0;
8634         rsurface.ent_qwskin = -1;
8635         rsurface.ent_shadertime = 0;
8636         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8637         if (rsurface.array_size < model->surfmesh.num_vertices)
8638                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
8639         rsurface.matrix = identitymatrix;
8640         rsurface.inversematrix = identitymatrix;
8641         rsurface.matrixscale = 1;
8642         rsurface.inversematrixscale = 1;
8643         R_EntityMatrix(&identitymatrix);
8644         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8645         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8646         rsurface.fograngerecip = r_refdef.fograngerecip;
8647         rsurface.fogheightfade = r_refdef.fogheightfade;
8648         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8649         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8650         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8651         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8652         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8653         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8654         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8655         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8656         rsurface.colormod[3] = 1;
8657         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);
8658         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8659         rsurface.frameblend[0].lerp = 1;
8660         rsurface.ent_alttextures = false;
8661         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8662         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8663         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8664         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
8665         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8666         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8667         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
8668         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8669         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8670         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
8671         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8672         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8673         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
8674         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8675         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8676         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
8677         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8678         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8679         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
8680         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8681         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8682         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
8683         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8684         rsurface.modelelement3i = model->surfmesh.data_element3i;
8685         rsurface.modelelement3s = model->surfmesh.data_element3s;
8686         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
8687         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
8688         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8689         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
8690         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
8691         rsurface.modelsurfaces = model->data_surfaces;
8692         rsurface.generatedvertex = false;
8693         rsurface.vertex3f  = rsurface.modelvertex3f;
8694         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
8695         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8696         rsurface.svector3f = rsurface.modelsvector3f;
8697         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
8698         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8699         rsurface.tvector3f = rsurface.modeltvector3f;
8700         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
8701         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8702         rsurface.normal3f  = rsurface.modelnormal3f;
8703         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
8704         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8705         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
8706 }
8707
8708 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8709 {
8710         dp_model_t *model = ent->model;
8711         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8712         //      return;
8713         rsurface.entity = (entity_render_t *)ent;
8714         rsurface.skeleton = ent->skeleton;
8715         rsurface.ent_skinnum = ent->skinnum;
8716         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;
8717         rsurface.ent_shadertime = ent->shadertime;
8718         rsurface.ent_flags = ent->flags;
8719         if (rsurface.array_size < model->surfmesh.num_vertices)
8720                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
8721         rsurface.matrix = ent->matrix;
8722         rsurface.inversematrix = ent->inversematrix;
8723         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8724         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8725         R_EntityMatrix(&rsurface.matrix);
8726         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8727         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8728         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8729         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8730         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8731         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8732         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8733         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8734         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8735         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8736         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8737         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8738         rsurface.colormod[3] = ent->alpha;
8739         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8740         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8741         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8742         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8743         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8744         if (ent->model->brush.submodel && !prepass)
8745         {
8746                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8747                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8748         }
8749         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
8750         {
8751                 if (ent->animcache_vertex3f && !r_framedata_failed)
8752                 {
8753                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8754                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8755                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8756                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8757                 }
8758                 else if (wanttangents)
8759                 {
8760                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
8761                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
8762                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
8763                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
8764                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
8765                 }
8766                 else if (wantnormals)
8767                 {
8768                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
8769                         rsurface.modelsvector3f = NULL;
8770                         rsurface.modeltvector3f = NULL;
8771                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
8772                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
8773                 }
8774                 else
8775                 {
8776                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
8777                         rsurface.modelsvector3f = NULL;
8778                         rsurface.modeltvector3f = NULL;
8779                         rsurface.modelnormal3f = NULL;
8780                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
8781                 }
8782                 rsurface.modelvertex3f_bufferobject = 0;
8783                 rsurface.modelvertex3f_bufferoffset = 0;
8784                 rsurface.modelsvector3f_bufferobject = 0;
8785                 rsurface.modelsvector3f_bufferoffset = 0;
8786                 rsurface.modeltvector3f_bufferobject = 0;
8787                 rsurface.modeltvector3f_bufferoffset = 0;
8788                 rsurface.modelnormal3f_bufferobject = 0;
8789                 rsurface.modelnormal3f_bufferoffset = 0;
8790                 rsurface.generatedvertex = true;
8791         }
8792         else
8793         {
8794                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8795                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
8796                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8797                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8798                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
8799                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8800                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8801                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
8802                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8803                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8804                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
8805                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8806                 rsurface.generatedvertex = false;
8807         }
8808         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8809         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
8810         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8811         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8812         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
8813         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8814         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8815         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
8816         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8817         rsurface.modelelement3i = model->surfmesh.data_element3i;
8818         rsurface.modelelement3s = model->surfmesh.data_element3s;
8819         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
8820         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
8821         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8822         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
8823         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
8824         rsurface.modelsurfaces = model->data_surfaces;
8825         rsurface.vertex3f  = rsurface.modelvertex3f;
8826         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
8827         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8828         rsurface.svector3f = rsurface.modelsvector3f;
8829         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
8830         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8831         rsurface.tvector3f = rsurface.modeltvector3f;
8832         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
8833         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8834         rsurface.normal3f  = rsurface.modelnormal3f;
8835         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
8836         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8837         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
8838 }
8839
8840 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)
8841 {
8842         rsurface.entity = r_refdef.scene.worldentity;
8843         rsurface.skeleton = NULL;
8844         rsurface.ent_skinnum = 0;
8845         rsurface.ent_qwskin = -1;
8846         rsurface.ent_shadertime = shadertime;
8847         rsurface.ent_flags = entflags;
8848         rsurface.modelnum_vertices = numvertices;
8849         rsurface.modelnum_triangles = numtriangles;
8850         if (rsurface.array_size < rsurface.modelnum_vertices)
8851                 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
8852         rsurface.matrix = *matrix;
8853         rsurface.inversematrix = *inversematrix;
8854         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8855         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8856         R_EntityMatrix(&rsurface.matrix);
8857         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8858         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8859         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8860         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8861         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8862         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8863         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8864         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8865         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8866         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8867         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8868         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8869         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);
8870         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8871         rsurface.frameblend[0].lerp = 1;
8872         rsurface.ent_alttextures = false;
8873         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8874         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8875         if (wanttangents)
8876         {
8877                 rsurface.modelvertex3f = vertex3f;
8878                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
8879                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
8880                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
8881         }
8882         else if (wantnormals)
8883         {
8884                 rsurface.modelvertex3f = vertex3f;
8885                 rsurface.modelsvector3f = NULL;
8886                 rsurface.modeltvector3f = NULL;
8887                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
8888         }
8889         else
8890         {
8891                 rsurface.modelvertex3f = vertex3f;
8892                 rsurface.modelsvector3f = NULL;
8893                 rsurface.modeltvector3f = NULL;
8894                 rsurface.modelnormal3f = NULL;
8895         }
8896         rsurface.modelvertex3f_bufferobject = 0;
8897         rsurface.modelvertex3f_bufferoffset = 0;
8898         rsurface.modelsvector3f_bufferobject = 0;
8899         rsurface.modelsvector3f_bufferoffset = 0;
8900         rsurface.modeltvector3f_bufferobject = 0;
8901         rsurface.modeltvector3f_bufferoffset = 0;
8902         rsurface.modelnormal3f_bufferobject = 0;
8903         rsurface.modelnormal3f_bufferoffset = 0;
8904         rsurface.generatedvertex = true;
8905         rsurface.modellightmapcolor4f  = color4f;
8906         rsurface.modellightmapcolor4f_bufferobject = 0;
8907         rsurface.modellightmapcolor4f_bufferoffset = 0;
8908         rsurface.modeltexcoordtexture2f  = texcoord2f;
8909         rsurface.modeltexcoordtexture2f_bufferobject = 0;
8910         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8911         rsurface.modeltexcoordlightmap2f  = NULL;
8912         rsurface.modeltexcoordlightmap2f_bufferobject = 0;
8913         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8914         rsurface.modelelement3i = element3i;
8915         rsurface.modelelement3s = element3s;
8916         rsurface.modelelement3i_bufferobject = 0;
8917         rsurface.modelelement3s_bufferobject = 0;
8918         rsurface.modellightmapoffsets = NULL;
8919         rsurface.modelsurfaces = NULL;
8920         rsurface.vertex3f  = rsurface.modelvertex3f;
8921         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
8922         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8923         rsurface.svector3f = rsurface.modelsvector3f;
8924         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
8925         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8926         rsurface.tvector3f = rsurface.modeltvector3f;
8927         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
8928         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8929         rsurface.normal3f  = rsurface.modelnormal3f;
8930         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
8931         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8932         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
8933
8934         if (rsurface.modelnum_vertices && rsurface.modelelement3i)
8935         {
8936                 if ((wantnormals || wanttangents) && !normal3f)
8937                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8938                 if (wanttangents && !svector3f)
8939                         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);
8940         }
8941 }
8942
8943 float RSurf_FogPoint(const float *v)
8944 {
8945         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8946         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8947         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8948         float FogHeightFade = r_refdef.fogheightfade;
8949         float fogfrac;
8950         unsigned int fogmasktableindex;
8951         if (r_refdef.fogplaneviewabove)
8952                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8953         else
8954                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8955         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8956         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8957 }
8958
8959 float RSurf_FogVertex(const float *v)
8960 {
8961         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8962         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8963         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8964         float FogHeightFade = rsurface.fogheightfade;
8965         float fogfrac;
8966         unsigned int fogmasktableindex;
8967         if (r_refdef.fogplaneviewabove)
8968                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8969         else
8970                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8971         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8972         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8973 }
8974
8975 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8976 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8977 {
8978         int deformindex;
8979         int texturesurfaceindex;
8980         int i, j;
8981         float amplitude;
8982         float animpos;
8983         float scale;
8984         const float *v1, *in_tc;
8985         float *out_tc;
8986         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8987         float waveparms[4];
8988         q3shaderinfo_deform_t *deform;
8989         // 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
8990         if (rsurface.generatedvertex)
8991         {
8992                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
8993                         generatenormals = true;
8994                 for (i = 0;i < Q3MAXDEFORMS;i++)
8995                 {
8996                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
8997                         {
8998                                 generatetangents = true;
8999                                 generatenormals = true;
9000                         }
9001                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
9002                                 generatenormals = true;
9003                 }
9004                 if (generatenormals && !rsurface.modelnormal3f)
9005                 {
9006                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9007                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
9008                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
9009                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9010                 }
9011                 if (generatetangents && !rsurface.modelsvector3f)
9012                 {
9013                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9014                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
9015                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
9016                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9017                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
9018                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
9019                         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);
9020                 }
9021         }
9022         rsurface.vertex3f  = rsurface.modelvertex3f;
9023         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9024         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9025         rsurface.svector3f = rsurface.modelsvector3f;
9026         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9027         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9028         rsurface.tvector3f = rsurface.modeltvector3f;
9029         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9030         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9031         rsurface.normal3f  = rsurface.modelnormal3f;
9032         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9033         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9034         // if vertices are deformed (sprite flares and things in maps, possibly
9035         // water waves, bulges and other deformations), generate them into
9036         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
9037         // (may be static model data or generated data for an animated model, or
9038         //  the previous deform pass)
9039         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
9040         {
9041                 switch (deform->deform)
9042                 {
9043                 default:
9044                 case Q3DEFORM_PROJECTIONSHADOW:
9045                 case Q3DEFORM_TEXT0:
9046                 case Q3DEFORM_TEXT1:
9047                 case Q3DEFORM_TEXT2:
9048                 case Q3DEFORM_TEXT3:
9049                 case Q3DEFORM_TEXT4:
9050                 case Q3DEFORM_TEXT5:
9051                 case Q3DEFORM_TEXT6:
9052                 case Q3DEFORM_TEXT7:
9053                 case Q3DEFORM_NONE:
9054                         break;
9055                 case Q3DEFORM_AUTOSPRITE:
9056                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9057                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9058                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9059                         VectorNormalize(newforward);
9060                         VectorNormalize(newright);
9061                         VectorNormalize(newup);
9062                         // make deformed versions of only the model vertices used by the specified surfaces
9063                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9064                         {
9065                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9066                                 // a single autosprite surface can contain multiple sprites...
9067                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9068                                 {
9069                                         VectorClear(center);
9070                                         for (i = 0;i < 4;i++)
9071                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9072                                         VectorScale(center, 0.25f, center);
9073                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
9074                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
9075                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
9076                                         for (i = 0;i < 4;i++)
9077                                         {
9078                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
9079                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9080                                         }
9081                                 }
9082                                 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);
9083                                 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);
9084                         }
9085                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9086                         rsurface.vertex3f_bufferobject = 0;
9087                         rsurface.vertex3f_bufferoffset = 0;
9088                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9089                         rsurface.svector3f_bufferobject = 0;
9090                         rsurface.svector3f_bufferoffset = 0;
9091                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9092                         rsurface.tvector3f_bufferobject = 0;
9093                         rsurface.tvector3f_bufferoffset = 0;
9094                         rsurface.normal3f = rsurface.array_deformednormal3f;
9095                         rsurface.normal3f_bufferobject = 0;
9096                         rsurface.normal3f_bufferoffset = 0;
9097                         break;
9098                 case Q3DEFORM_AUTOSPRITE2:
9099                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9100                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9101                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9102                         VectorNormalize(newforward);
9103                         VectorNormalize(newright);
9104                         VectorNormalize(newup);
9105                         // make deformed versions of only the model vertices used by the specified surfaces
9106                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9107                         {
9108                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9109                                 const float *v1, *v2;
9110                                 vec3_t start, end;
9111                                 float f, l;
9112                                 struct
9113                                 {
9114                                         float length2;
9115                                         const float *v1;
9116                                         const float *v2;
9117                                 }
9118                                 shortest[2];
9119                                 memset(shortest, 0, sizeof(shortest));
9120                                 // a single autosprite surface can contain multiple sprites...
9121                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9122                                 {
9123                                         VectorClear(center);
9124                                         for (i = 0;i < 4;i++)
9125                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9126                                         VectorScale(center, 0.25f, center);
9127                                         // find the two shortest edges, then use them to define the
9128                                         // axis vectors for rotating around the central axis
9129                                         for (i = 0;i < 6;i++)
9130                                         {
9131                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
9132                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
9133 #if 0
9134                                                 Debug_PolygonBegin(NULL, 0);
9135                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
9136                                                 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);
9137                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
9138                                                 Debug_PolygonEnd();
9139 #endif
9140                                                 l = VectorDistance2(v1, v2);
9141                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9142                                                 if (v1[2] != v2[2])
9143                                                         l += (1.0f / 1024.0f);
9144                                                 if (shortest[0].length2 > l || i == 0)
9145                                                 {
9146                                                         shortest[1] = shortest[0];
9147                                                         shortest[0].length2 = l;
9148                                                         shortest[0].v1 = v1;
9149                                                         shortest[0].v2 = v2;
9150                                                 }
9151                                                 else if (shortest[1].length2 > l || i == 1)
9152                                                 {
9153                                                         shortest[1].length2 = l;
9154                                                         shortest[1].v1 = v1;
9155                                                         shortest[1].v2 = v2;
9156                                                 }
9157                                         }
9158                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9159                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9160 #if 0
9161                                         Debug_PolygonBegin(NULL, 0);
9162                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
9163                                         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);
9164                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
9165                                         Debug_PolygonEnd();
9166 #endif
9167                                         // this calculates the right vector from the shortest edge
9168                                         // and the up vector from the edge midpoints
9169                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9170                                         VectorNormalize(right);
9171                                         VectorSubtract(end, start, up);
9172                                         VectorNormalize(up);
9173                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9174                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9175                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9176                                         VectorNegate(forward, forward);
9177                                         VectorReflect(forward, 0, up, forward);
9178                                         VectorNormalize(forward);
9179                                         CrossProduct(up, forward, newright);
9180                                         VectorNormalize(newright);
9181 #if 0
9182                                         Debug_PolygonBegin(NULL, 0);
9183                                         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);
9184                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
9185                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
9186                                         Debug_PolygonEnd();
9187 #endif
9188 #if 0
9189                                         Debug_PolygonBegin(NULL, 0);
9190                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
9191                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
9192                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
9193                                         Debug_PolygonEnd();
9194 #endif
9195                                         // rotate the quad around the up axis vector, this is made
9196                                         // especially easy by the fact we know the quad is flat,
9197                                         // so we only have to subtract the center position and
9198                                         // measure distance along the right vector, and then
9199                                         // multiply that by the newright vector and add back the
9200                                         // center position
9201                                         // we also need to subtract the old position to undo the
9202                                         // displacement from the center, which we do with a
9203                                         // DotProduct, the subtraction/addition of center is also
9204                                         // optimized into DotProducts here
9205                                         l = DotProduct(right, center);
9206                                         for (i = 0;i < 4;i++)
9207                                         {
9208                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
9209                                                 f = DotProduct(right, v1) - l;
9210                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9211                                         }
9212                                 }
9213                                 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);
9214                                 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);
9215                         }
9216                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9217                         rsurface.vertex3f_bufferobject = 0;
9218                         rsurface.vertex3f_bufferoffset = 0;
9219                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9220                         rsurface.svector3f_bufferobject = 0;
9221                         rsurface.svector3f_bufferoffset = 0;
9222                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9223                         rsurface.tvector3f_bufferobject = 0;
9224                         rsurface.tvector3f_bufferoffset = 0;
9225                         rsurface.normal3f = rsurface.array_deformednormal3f;
9226                         rsurface.normal3f_bufferobject = 0;
9227                         rsurface.normal3f_bufferoffset = 0;
9228                         break;
9229                 case Q3DEFORM_NORMAL:
9230                         // deform the normals to make reflections wavey
9231                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9232                         {
9233                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9234                                 for (j = 0;j < surface->num_vertices;j++)
9235                                 {
9236                                         float vertex[3];
9237                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
9238                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
9239                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
9240                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9241                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9242                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9243                                         VectorNormalize(normal);
9244                                 }
9245                                 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);
9246                         }
9247                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9248                         rsurface.svector3f_bufferobject = 0;
9249                         rsurface.svector3f_bufferoffset = 0;
9250                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9251                         rsurface.tvector3f_bufferobject = 0;
9252                         rsurface.tvector3f_bufferoffset = 0;
9253                         rsurface.normal3f = rsurface.array_deformednormal3f;
9254                         rsurface.normal3f_bufferobject = 0;
9255                         rsurface.normal3f_bufferoffset = 0;
9256                         break;
9257                 case Q3DEFORM_WAVE:
9258                         // deform vertex array to make wavey water and flags and such
9259                         waveparms[0] = deform->waveparms[0];
9260                         waveparms[1] = deform->waveparms[1];
9261                         waveparms[2] = deform->waveparms[2];
9262                         waveparms[3] = deform->waveparms[3];
9263                         // this is how a divisor of vertex influence on deformation
9264                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9265                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9266                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9267                         {
9268                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9269                                 for (j = 0;j < surface->num_vertices;j++)
9270                                 {
9271                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
9272                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9273                                         // if the wavefunc depends on time, evaluate it per-vertex
9274                                         if (waveparms[3])
9275                                         {
9276                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
9277                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9278                                         }
9279                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9280                                 }
9281                         }
9282                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9283                         rsurface.vertex3f_bufferobject = 0;
9284                         rsurface.vertex3f_bufferoffset = 0;
9285                         break;
9286                 case Q3DEFORM_BULGE:
9287                         // deform vertex array to make the surface have moving bulges
9288                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9289                         {
9290                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9291                                 for (j = 0;j < surface->num_vertices;j++)
9292                                 {
9293                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
9294                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9295                                 }
9296                         }
9297                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9298                         rsurface.vertex3f_bufferobject = 0;
9299                         rsurface.vertex3f_bufferoffset = 0;
9300                         break;
9301                 case Q3DEFORM_MOVE:
9302                         // deform vertex array
9303                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9304                         VectorScale(deform->parms, scale, waveparms);
9305                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9306                         {
9307                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9308                                 for (j = 0;j < surface->num_vertices;j++)
9309                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9310                         }
9311                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9312                         rsurface.vertex3f_bufferobject = 0;
9313                         rsurface.vertex3f_bufferoffset = 0;
9314                         break;
9315                 }
9316         }
9317         // generate texcoords based on the chosen texcoord source
9318         switch(rsurface.texture->tcgen.tcgen)
9319         {
9320         default:
9321         case Q3TCGEN_TEXTURE:
9322                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
9323                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
9324                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9325                 break;
9326         case Q3TCGEN_LIGHTMAP:
9327                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
9328                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
9329                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
9330                 break;
9331         case Q3TCGEN_VECTOR:
9332                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9333                 {
9334                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9335                         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)
9336                         {
9337                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
9338                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
9339                         }
9340                 }
9341                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9342                 rsurface.texcoordtexture2f_bufferobject  = 0;
9343                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9344                 break;
9345         case Q3TCGEN_ENVIRONMENT:
9346                 // make environment reflections using a spheremap
9347                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9348                 {
9349                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9350                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
9351                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
9352                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
9353                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
9354                         {
9355                                 // identical to Q3A's method, but executed in worldspace so
9356                                 // carried models can be shiny too
9357
9358                                 float viewer[3], d, reflected[3], worldreflected[3];
9359
9360                                 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
9361                                 // VectorNormalize(viewer);
9362
9363                                 d = DotProduct(normal, viewer);
9364
9365                                 reflected[0] = normal[0]*2*d - viewer[0];
9366                                 reflected[1] = normal[1]*2*d - viewer[1];
9367                                 reflected[2] = normal[2]*2*d - viewer[2];
9368                                 // note: this is proportinal to viewer, so we can normalize later
9369
9370                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9371                                 VectorNormalize(worldreflected);
9372
9373                                 // note: this sphere map only uses world x and z!
9374                                 // so positive and negative y will LOOK THE SAME.
9375                                 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
9376                                 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
9377                         }
9378                 }
9379                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9380                 rsurface.texcoordtexture2f_bufferobject  = 0;
9381                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9382                 break;
9383         }
9384         // the only tcmod that needs software vertex processing is turbulent, so
9385         // check for it here and apply the changes if needed
9386         // and we only support that as the first one
9387         // (handling a mixture of turbulent and other tcmods would be problematic
9388         //  without punting it entirely to a software path)
9389         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9390         {
9391                 amplitude = rsurface.texture->tcmods[0].parms[1];
9392                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
9393                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9394                 {
9395                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9396                         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)
9397                         {
9398                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9399                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9400                         }
9401                 }
9402                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9403                 rsurface.texcoordtexture2f_bufferobject  = 0;
9404                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9405         }
9406         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
9407         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
9408         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9409         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
9410 }
9411
9412 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9413 {
9414         int i, j;
9415         const msurface_t *surface = texturesurfacelist[0];
9416         const msurface_t *surface2;
9417         int firstvertex;
9418         int endvertex;
9419         int numvertices;
9420         int numtriangles;
9421         // TODO: lock all array ranges before render, rather than on each surface
9422         if (texturenumsurfaces == 1)
9423         {
9424                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9425                 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);
9426         }
9427         else if (r_batchmode.integer == 2)
9428         {
9429                 #define MAXBATCHTRIANGLES 4096
9430                 int batchtriangles = 0;
9431                 static int batchelements[MAXBATCHTRIANGLES*3];
9432                 for (i = 0;i < texturenumsurfaces;i = j)
9433                 {
9434                         surface = texturesurfacelist[i];
9435                         j = i + 1;
9436                         if (surface->num_triangles > MAXBATCHTRIANGLES)
9437                         {
9438                                 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);
9439                                 continue;
9440                         }
9441                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9442                         batchtriangles = surface->num_triangles;
9443                         firstvertex = surface->num_firstvertex;
9444                         endvertex = surface->num_firstvertex + surface->num_vertices;
9445                         for (;j < texturenumsurfaces;j++)
9446                         {
9447                                 surface2 = texturesurfacelist[j];
9448                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9449                                         break;
9450                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9451                                 batchtriangles += surface2->num_triangles;
9452                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
9453                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9454                         }
9455                         surface2 = texturesurfacelist[j-1];
9456                         numvertices = endvertex - firstvertex;
9457                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9458                 }
9459         }
9460         else if (r_batchmode.integer == 1)
9461         {
9462                 for (i = 0;i < texturenumsurfaces;i = j)
9463                 {
9464                         surface = texturesurfacelist[i];
9465                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9466                                 if (texturesurfacelist[j] != surface2)
9467                                         break;
9468                         surface2 = texturesurfacelist[j-1];
9469                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9470                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9471                         GL_LockArrays(surface->num_firstvertex, numvertices);
9472                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9473                 }
9474         }
9475         else
9476         {
9477                 for (i = 0;i < texturenumsurfaces;i++)
9478                 {
9479                         surface = texturesurfacelist[i];
9480                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9481                         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);
9482                 }
9483         }
9484 }
9485
9486 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
9487 {
9488         switch(vid.renderpath)
9489         {
9490         case RENDERPATH_CGGL:
9491 #ifdef SUPPORTCG
9492                 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , R_GetTexture(surface->lightmaptexture ));CHECKCGERROR
9493                 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, R_GetTexture(surface->deluxemaptexture));CHECKCGERROR
9494 #endif
9495                 break;
9496         case RENDERPATH_GL20:
9497                 if (r_glsl_permutation->loc_Texture_Lightmap  >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , R_GetTexture(surface->lightmaptexture ));
9498                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, R_GetTexture(surface->deluxemaptexture));
9499                 break;
9500         case RENDERPATH_GL13:
9501         case RENDERPATH_GL11:
9502                 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
9503                 break;
9504         }
9505 }
9506
9507 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
9508 {
9509         // pick the closest matching water plane and bind textures
9510         int planeindex, vertexindex;
9511         float d, bestd;
9512         vec3_t vert;
9513         const float *v;
9514         r_waterstate_waterplane_t *p, *bestp;
9515         bestd = 0;
9516         bestp = NULL;
9517         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9518         {
9519                 d = 0;
9520                 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
9521                 {
9522                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9523                         d += fabs(PlaneDiff(vert, &p->plane));
9524                 }
9525                 if (bestd > d || !bestp)
9526                 {
9527                         bestd = d;
9528                         bestp = p;
9529                 }
9530         }
9531         switch(vid.renderpath)
9532         {
9533         case RENDERPATH_CGGL:
9534 #ifdef SUPPORTCG
9535                 if (r_cg_permutation->fp_Texture_Refraction) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? R_GetTexture(bestp->texture_refraction) : R_GetTexture(r_texture_black));CHECKCGERROR
9536                 if (r_cg_permutation->fp_Texture_Reflection) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? R_GetTexture(bestp->texture_reflection) : R_GetTexture(r_texture_black));CHECKCGERROR
9537 #endif
9538                 break;
9539         case RENDERPATH_GL20:
9540                 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? R_GetTexture(bestp->texture_refraction) : R_GetTexture(r_texture_black));
9541                 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? R_GetTexture(bestp->texture_reflection) : R_GetTexture(r_texture_black));
9542                 break;
9543         case RENDERPATH_GL13:
9544         case RENDERPATH_GL11:
9545                 break;
9546         }
9547 }
9548
9549 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9550 {
9551         int i;
9552         const msurface_t *surface;
9553         if (r_waterstate.renderingscene)
9554                 return;
9555         for (i = 0;i < texturenumsurfaces;i++)
9556         {
9557                 surface = texturesurfacelist[i];
9558                 RSurf_BindLightmapForSurface(surface);
9559                 RSurf_BindReflectionForSurface(surface);
9560                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9561                 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);
9562         }
9563 }
9564
9565 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9566 {
9567         int i;
9568         int j;
9569         const msurface_t *surface = texturesurfacelist[0];
9570         const msurface_t *surface2;
9571         int firstvertex;
9572         int endvertex;
9573         int numvertices;
9574         int numtriangles;
9575         if (texturenumsurfaces == 1)
9576         {
9577                 RSurf_BindLightmapForSurface(surface);
9578                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9579                 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);
9580         }
9581         else if (r_batchmode.integer == 2)
9582         {
9583 #define MAXBATCHTRIANGLES 4096
9584                 int batchtriangles = 0;
9585                 static int batchelements[MAXBATCHTRIANGLES*3];
9586                 for (i = 0;i < texturenumsurfaces;i = j)
9587                 {
9588                         surface = texturesurfacelist[i];
9589                         RSurf_BindLightmapForSurface(surface);
9590                         j = i + 1;
9591                         if (surface->num_triangles > MAXBATCHTRIANGLES)
9592                         {
9593                                 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);
9594                                 continue;
9595                         }
9596                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9597                         batchtriangles = surface->num_triangles;
9598                         firstvertex = surface->num_firstvertex;
9599                         endvertex = surface->num_firstvertex + surface->num_vertices;
9600                         for (;j < texturenumsurfaces;j++)
9601                         {
9602                                 surface2 = texturesurfacelist[j];
9603                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9604                                         break;
9605                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9606                                 batchtriangles += surface2->num_triangles;
9607                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
9608                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9609                         }
9610                         surface2 = texturesurfacelist[j-1];
9611                         numvertices = endvertex - firstvertex;
9612                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9613                 }
9614         }
9615         else if (r_batchmode.integer == 1)
9616         {
9617 #if 0
9618                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
9619                 for (i = 0;i < texturenumsurfaces;i = j)
9620                 {
9621                         surface = texturesurfacelist[i];
9622                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9623                                 if (texturesurfacelist[j] != surface2)
9624                                         break;
9625                         Con_Printf(" %i", j - i);
9626                 }
9627                 Con_Printf("\n");
9628                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
9629 #endif
9630                 for (i = 0;i < texturenumsurfaces;i = j)
9631                 {
9632                         surface = texturesurfacelist[i];
9633                         RSurf_BindLightmapForSurface(surface);
9634                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9635                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
9636                                         break;
9637 #if 0
9638                         Con_Printf(" %i", j - i);
9639 #endif
9640                         surface2 = texturesurfacelist[j-1];
9641                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9642                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9643                         GL_LockArrays(surface->num_firstvertex, numvertices);
9644                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9645                 }
9646 #if 0
9647                 Con_Printf("\n");
9648 #endif
9649         }
9650         else
9651         {
9652                 for (i = 0;i < texturenumsurfaces;i++)
9653                 {
9654                         surface = texturesurfacelist[i];
9655                         RSurf_BindLightmapForSurface(surface);
9656                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9657                         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);
9658                 }
9659         }
9660 }
9661
9662 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9663 {
9664         int j;
9665         int texturesurfaceindex;
9666         if (r_showsurfaces.integer == 2)
9667         {
9668                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9669                 {
9670                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9671                         for (j = 0;j < surface->num_triangles;j++)
9672                         {
9673                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
9674                                 GL_Color(f, f, f, 1);
9675                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9676                         }
9677                 }
9678         }
9679         else
9680         {
9681                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9682                 {
9683                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9684                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
9685                         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);
9686                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9687                         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);
9688                 }
9689         }
9690 }
9691
9692 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9693 {
9694         int texturesurfaceindex;
9695         int i;
9696         const float *v;
9697         float *c2;
9698         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9699         {
9700                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9701                 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)
9702                 {
9703                         c2[0] = 0.5;
9704                         c2[1] = 0.5;
9705                         c2[2] = 0.5;
9706                         c2[3] = 1;
9707                 }
9708         }
9709         rsurface.lightmapcolor4f = rsurface.array_color4f;
9710         rsurface.lightmapcolor4f_bufferobject = 0;
9711         rsurface.lightmapcolor4f_bufferoffset = 0;
9712 }
9713
9714 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9715 {
9716         int texturesurfaceindex;
9717         int i;
9718         float f;
9719         const float *v;
9720         const float *c;
9721         float *c2;
9722         if (rsurface.lightmapcolor4f)
9723         {
9724                 // generate color arrays for the surfaces in this list
9725                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9726                 {
9727                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9728                         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)
9729                         {
9730                                 f = RSurf_FogVertex(v);
9731                                 c2[0] = c[0] * f;
9732                                 c2[1] = c[1] * f;
9733                                 c2[2] = c[2] * f;
9734                                 c2[3] = c[3];
9735                         }
9736                 }
9737         }
9738         else
9739         {
9740                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9741                 {
9742                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9743                         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)
9744                         {
9745                                 f = RSurf_FogVertex(v);
9746                                 c2[0] = f;
9747                                 c2[1] = f;
9748                                 c2[2] = f;
9749                                 c2[3] = 1;
9750                         }
9751                 }
9752         }
9753         rsurface.lightmapcolor4f = rsurface.array_color4f;
9754         rsurface.lightmapcolor4f_bufferobject = 0;
9755         rsurface.lightmapcolor4f_bufferoffset = 0;
9756 }
9757
9758 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9759 {
9760         int texturesurfaceindex;
9761         int i;
9762         float f;
9763         const float *v;
9764         const float *c;
9765         float *c2;
9766         if (!rsurface.lightmapcolor4f)
9767                 return;
9768         // generate color arrays for the surfaces in this list
9769         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9770         {
9771                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9772                 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)
9773                 {
9774                         f = RSurf_FogVertex(v);
9775                         c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9776                         c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9777                         c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9778                         c2[3] = c[3];
9779                 }
9780         }
9781         rsurface.lightmapcolor4f = rsurface.array_color4f;
9782         rsurface.lightmapcolor4f_bufferobject = 0;
9783         rsurface.lightmapcolor4f_bufferoffset = 0;
9784 }
9785
9786 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
9787 {
9788         int texturesurfaceindex;
9789         int i;
9790         const float *c;
9791         float *c2;
9792         if (!rsurface.lightmapcolor4f)
9793                 return;
9794         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9795         {
9796                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9797                 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)
9798                 {
9799                         c2[0] = c[0] * r;
9800                         c2[1] = c[1] * g;
9801                         c2[2] = c[2] * b;
9802                         c2[3] = c[3] * a;
9803                 }
9804         }
9805         rsurface.lightmapcolor4f = rsurface.array_color4f;
9806         rsurface.lightmapcolor4f_bufferobject = 0;
9807         rsurface.lightmapcolor4f_bufferoffset = 0;
9808 }
9809
9810 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9811 {
9812         int texturesurfaceindex;
9813         int i;
9814         const float *c;
9815         float *c2;
9816         if (!rsurface.lightmapcolor4f)
9817                 return;
9818         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9819         {
9820                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9821                 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)
9822                 {
9823                         c2[0] = c[0] + r_refdef.scene.ambient;
9824                         c2[1] = c[1] + r_refdef.scene.ambient;
9825                         c2[2] = c[2] + r_refdef.scene.ambient;
9826                         c2[3] = c[3];
9827                 }
9828         }
9829         rsurface.lightmapcolor4f = rsurface.array_color4f;
9830         rsurface.lightmapcolor4f_bufferobject = 0;
9831         rsurface.lightmapcolor4f_bufferoffset = 0;
9832 }
9833
9834 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9835 {
9836         // TODO: optimize
9837         rsurface.lightmapcolor4f = NULL;
9838         rsurface.lightmapcolor4f_bufferobject = 0;
9839         rsurface.lightmapcolor4f_bufferoffset = 0;
9840         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
9841         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
9842         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
9843         GL_Color(r, g, b, a);
9844         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
9845 }
9846
9847 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9848 {
9849         // TODO: optimize applyfog && applycolor case
9850         // just apply fog if necessary, and tint the fog color array if necessary
9851         rsurface.lightmapcolor4f = NULL;
9852         rsurface.lightmapcolor4f_bufferobject = 0;
9853         rsurface.lightmapcolor4f_bufferoffset = 0;
9854         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
9855         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
9856         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
9857         GL_Color(r, g, b, a);
9858         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9859 }
9860
9861 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9862 {
9863         int texturesurfaceindex;
9864         int i;
9865         float *c;
9866         // TODO: optimize
9867         if (texturesurfacelist[0]->lightmapinfo)
9868         {
9869                 // generate color arrays for the surfaces in this list
9870                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9871                 {
9872                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9873                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
9874                         {
9875                                 if (surface->lightmapinfo->samples)
9876                                 {
9877                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
9878                                         float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
9879                                         VectorScale(lm, scale, c);
9880                                         if (surface->lightmapinfo->styles[1] != 255)
9881                                         {
9882                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9883                                                 lm += size3;
9884                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
9885                                                 VectorMA(c, scale, lm, c);
9886                                                 if (surface->lightmapinfo->styles[2] != 255)
9887                                                 {
9888                                                         lm += size3;
9889                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
9890                                                         VectorMA(c, scale, lm, c);
9891                                                         if (surface->lightmapinfo->styles[3] != 255)
9892                                                         {
9893                                                                 lm += size3;
9894                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
9895                                                                 VectorMA(c, scale, lm, c);
9896                                                         }
9897                                                 }
9898                                         }
9899                                 }
9900                                 else
9901                                         VectorClear(c);
9902                                 c[3] = 1;
9903                         }
9904                 }
9905                 rsurface.lightmapcolor4f = rsurface.array_color4f;
9906                 rsurface.lightmapcolor4f_bufferobject = 0;
9907                 rsurface.lightmapcolor4f_bufferoffset = 0;
9908         }
9909         else
9910         {
9911                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
9912                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
9913                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
9914         }
9915         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
9916         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
9917         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
9918         GL_Color(r, g, b, a);
9919         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9920 }
9921
9922 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
9923 {
9924         int texturesurfaceindex;
9925         int i;
9926         float f;
9927         float alpha;
9928         const float *v;
9929         const float *n;
9930         float *c;
9931         vec3_t ambientcolor;
9932         vec3_t diffusecolor;
9933         vec3_t lightdir;
9934         // TODO: optimize
9935         // model lighting
9936         VectorCopy(rsurface.modellight_lightdir, lightdir);
9937         f = 0.5f * r_refdef.lightmapintensity;
9938         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9939         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9940         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9941         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9942         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9943         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9944         alpha = *a;
9945         if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
9946         {
9947                 // generate color arrays for the surfaces in this list
9948                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9949                 {
9950                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9951                         int numverts = surface->num_vertices;
9952                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
9953                         n = rsurface.normal3f + 3 * surface->num_firstvertex;
9954                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
9955                         // q3-style directional shading
9956                         for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
9957                         {
9958                                 if ((f = DotProduct(n, lightdir)) > 0)
9959                                         VectorMA(ambientcolor, f, diffusecolor, c);
9960                                 else
9961                                         VectorCopy(ambientcolor, c);
9962                                 c[3] = alpha;
9963                         }
9964                 }
9965                 *r = 1;
9966                 *g = 1;
9967                 *b = 1;
9968                 *a = 1;
9969                 rsurface.lightmapcolor4f = rsurface.array_color4f;
9970                 rsurface.lightmapcolor4f_bufferobject = 0;
9971                 rsurface.lightmapcolor4f_bufferoffset = 0;
9972                 *applycolor = false;
9973         }
9974         else
9975         {
9976                 *r = ambientcolor[0];
9977                 *g = ambientcolor[1];
9978                 *b = ambientcolor[2];
9979                 rsurface.lightmapcolor4f = NULL;
9980                 rsurface.lightmapcolor4f_bufferobject = 0;
9981                 rsurface.lightmapcolor4f_bufferoffset = 0;
9982         }
9983 }
9984
9985 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9986 {
9987         RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
9988         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
9989         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
9990         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
9991         GL_Color(r, g, b, a);
9992         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9993 }
9994
9995 void RSurf_SetupDepthAndCulling(void)
9996 {
9997         // submodels are biased to avoid z-fighting with world surfaces that they
9998         // may be exactly overlapping (avoids z-fighting artifacts on certain
9999         // doors and things in Quake maps)
10000         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10001         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10002         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10003         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10004 }
10005
10006 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10007 {
10008         // transparent sky would be ridiculous
10009         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10010                 return;
10011         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10012         skyrenderlater = true;
10013         RSurf_SetupDepthAndCulling();
10014         GL_DepthMask(true);
10015         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10016         // skymasking on them, and Quake3 never did sky masking (unlike
10017         // software Quake and software Quake2), so disable the sky masking
10018         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10019         // and skymasking also looks very bad when noclipping outside the
10020         // level, so don't use it then either.
10021         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
10022         {
10023                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10024                 R_Mesh_ColorPointer(NULL, 0, 0);
10025                 R_Mesh_ResetTextureState();
10026                 if (skyrendermasked)
10027                 {
10028                         R_SetupShader_DepthOrShadow();
10029                         // depth-only (masking)
10030                         GL_ColorMask(0,0,0,0);
10031                         // just to make sure that braindead drivers don't draw
10032                         // anything despite that colormask...
10033                         GL_BlendFunc(GL_ZERO, GL_ONE);
10034                 }
10035                 else
10036                 {
10037                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10038                         // fog sky
10039                         GL_BlendFunc(GL_ONE, GL_ZERO);
10040                 }
10041                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10042                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10043                 if (skyrendermasked)
10044                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10045         }
10046         R_Mesh_ResetTextureState();
10047         GL_Color(1, 1, 1, 1);
10048 }
10049
10050 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10051 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10052 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10053 {
10054         qboolean reflect = (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)) && !prepass;
10055         qboolean refract = (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !prepass;
10056
10057         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
10058                 return;
10059
10060         if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
10061                 R_Mesh_ColorPointer(NULL, 0, 0);
10062         else
10063                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
10064
10065         if (refract)
10066         {
10067                 // render background
10068                 GL_BlendFunc(GL_ONE, GL_ZERO);
10069                 GL_DepthMask(true);
10070                 GL_AlphaTest(false);
10071
10072                 GL_Color(1, 1, 1, 1);
10073                 R_Mesh_ColorPointer(NULL, 0, 0);
10074
10075                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
10076                 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10077                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10078                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
10079                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
10080                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
10081                 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10082                 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10083                 GL_LockArrays(0, 0);
10084
10085                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
10086                 GL_DepthMask(false);
10087                 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
10088                         R_Mesh_ColorPointer(NULL, 0, 0);
10089                 else
10090                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
10091         }
10092
10093         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
10094
10095         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10096         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10097         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
10098         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
10099         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
10100         if (!prepass)
10101                 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10102
10103         if (refract)
10104         {
10105                 GL_BlendFunc(GL_ONE, GL_ZERO);
10106                 GL_DepthMask(true);
10107                 GL_AlphaTest(false);
10108         }
10109         else
10110         {
10111                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
10112                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10113                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0 && !r_shadow_usingdeferredprepass);
10114         }
10115
10116         if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10117         {
10118                 if (refract || reflect)
10119                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10120                 else
10121                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10122         }
10123         else
10124         {
10125                 if (refract || reflect)
10126                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10127                 else
10128                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10129         }
10130         GL_LockArrays(0, 0);
10131 }
10132
10133 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10134 {
10135         // OpenGL 1.3 path - anything not completely ancient
10136         int texturesurfaceindex;
10137         qboolean applycolor;
10138         qboolean applyfog;
10139         int layerindex;
10140         const texturelayer_t *layer;
10141         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10142
10143         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10144         {
10145                 vec4_t layercolor;
10146                 int layertexrgbscale;
10147                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10148                 {
10149                         if (layerindex == 0)
10150                                 GL_AlphaTest(true);
10151                         else
10152                         {
10153                                 GL_AlphaTest(false);
10154                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10155                         }
10156                 }
10157                 GL_DepthMask(layer->depthmask && writedepth);
10158                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10159                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10160                 {
10161                         layertexrgbscale = 4;
10162                         VectorScale(layer->color, 0.25f, layercolor);
10163                 }
10164                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10165                 {
10166                         layertexrgbscale = 2;
10167                         VectorScale(layer->color, 0.5f, layercolor);
10168                 }
10169                 else
10170                 {
10171                         layertexrgbscale = 1;
10172                         VectorScale(layer->color, 1.0f, layercolor);
10173                 }
10174                 layercolor[3] = layer->color[3];
10175                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10176                 R_Mesh_ColorPointer(NULL, 0, 0);
10177                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10178                 switch (layer->type)
10179                 {
10180                 case TEXTURELAYERTYPE_LITTEXTURE:
10181                         // single-pass lightmapped texture with 2x rgbscale
10182                         //R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
10183                         R_Mesh_TexMatrix(0, NULL);
10184                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10185                         R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10186                         R_Mesh_TexBind(1, R_GetTexture(layer->texture));
10187                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10188                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10189                         R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10190                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10191                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10192                         else if (rsurface.uselightmaptexture)
10193                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10194                         else
10195                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10196                         break;
10197                 case TEXTURELAYERTYPE_TEXTURE:
10198                         // singletexture unlit texture with transparency support
10199                         R_Mesh_TexBind(0, R_GetTexture(layer->texture));
10200                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10201                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10202                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10203                         R_Mesh_TexBind(1, 0);
10204                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10205                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10206                         break;
10207                 case TEXTURELAYERTYPE_FOG:
10208                         // singletexture fogging
10209                         if (layer->texture)
10210                         {
10211                                 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
10212                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10213                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10214                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10215                         }
10216                         else
10217                         {
10218                                 R_Mesh_TexBind(0, 0);
10219                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10220                         }
10221                         R_Mesh_TexBind(1, 0);
10222                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10223                         // generate a color array for the fog pass
10224                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10225                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10226                         {
10227                                 int i;
10228                                 float f;
10229                                 const float *v;
10230                                 float *c;
10231                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10232                                 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)
10233                                 {
10234                                         f = 1 - RSurf_FogVertex(v);
10235                                         c[0] = layercolor[0];
10236                                         c[1] = layercolor[1];
10237                                         c[2] = layercolor[2];
10238                                         c[3] = f * layercolor[3];
10239                                 }
10240                         }
10241                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10242                         break;
10243                 default:
10244                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10245                 }
10246                 GL_LockArrays(0, 0);
10247         }
10248         CHECKGLERROR
10249         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10250         {
10251                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10252                 GL_AlphaTest(false);
10253         }
10254 }
10255
10256 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10257 {
10258         // OpenGL 1.1 - crusty old voodoo path
10259         int texturesurfaceindex;
10260         qboolean applyfog;
10261         int layerindex;
10262         const texturelayer_t *layer;
10263         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10264
10265         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10266         {
10267                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10268                 {
10269                         if (layerindex == 0)
10270                                 GL_AlphaTest(true);
10271                         else
10272                         {
10273                                 GL_AlphaTest(false);
10274                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10275                         }
10276                 }
10277                 GL_DepthMask(layer->depthmask && writedepth);
10278                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10279                 R_Mesh_ColorPointer(NULL, 0, 0);
10280                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10281                 switch (layer->type)
10282                 {
10283                 case TEXTURELAYERTYPE_LITTEXTURE:
10284                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10285                         {
10286                                 // two-pass lit texture with 2x rgbscale
10287                                 // first the lightmap pass
10288                                 //R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
10289                                 R_Mesh_TexMatrix(0, NULL);
10290                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10291                                 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10292                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10293                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10294                                 else if (rsurface.uselightmaptexture)
10295                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10296                                 else
10297                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10298                                 GL_LockArrays(0, 0);
10299                                 // then apply the texture to it
10300                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10301                                 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
10302                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10303                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10304                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10305                                 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);
10306                         }
10307                         else
10308                         {
10309                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10310                                 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
10311                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10312                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10313                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10314                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10315                                         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);
10316                                 else
10317                                         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);
10318                         }
10319                         break;
10320                 case TEXTURELAYERTYPE_TEXTURE:
10321                         // singletexture unlit texture with transparency support
10322                         R_Mesh_TexBind(0, R_GetTexture(layer->texture));
10323                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10324                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10325                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10326                         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);
10327                         break;
10328                 case TEXTURELAYERTYPE_FOG:
10329                         // singletexture fogging
10330                         if (layer->texture)
10331                         {
10332                                 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
10333                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10334                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10335                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10336                         }
10337                         else
10338                         {
10339                                 R_Mesh_TexBind(0, 0);
10340                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10341                         }
10342                         // generate a color array for the fog pass
10343                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10344                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10345                         {
10346                                 int i;
10347                                 float f;
10348                                 const float *v;
10349                                 float *c;
10350                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10351                                 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)
10352                                 {
10353                                         f = 1 - RSurf_FogVertex(v);
10354                                         c[0] = layer->color[0];
10355                                         c[1] = layer->color[1];
10356                                         c[2] = layer->color[2];
10357                                         c[3] = f * layer->color[3];
10358                                 }
10359                         }
10360                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10361                         break;
10362                 default:
10363                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10364                 }
10365                 GL_LockArrays(0, 0);
10366         }
10367         CHECKGLERROR
10368         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10369         {
10370                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10371                 GL_AlphaTest(false);
10372         }
10373 }
10374
10375 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10376 {
10377         float c[4];
10378
10379         GL_AlphaTest(false);
10380         R_Mesh_ColorPointer(NULL, 0, 0);
10381         R_Mesh_ResetTextureState();
10382         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10383
10384         if(rsurface.texture && rsurface.texture->currentskinframe)
10385         {
10386                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10387                 c[3] *= rsurface.texture->currentalpha;
10388         }
10389         else
10390         {
10391                 c[0] = 1;
10392                 c[1] = 0;
10393                 c[2] = 1;
10394                 c[3] = 1;
10395         }
10396
10397         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10398         {
10399                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10400                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10401                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10402         }
10403
10404         // brighten it up (as texture value 127 means "unlit")
10405         c[0] *= 2 * r_refdef.view.colorscale;
10406         c[1] *= 2 * r_refdef.view.colorscale;
10407         c[2] *= 2 * r_refdef.view.colorscale;
10408
10409         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10410                 c[3] *= r_wateralpha.value;
10411
10412         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10413         {
10414                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10415                 GL_DepthMask(false);
10416         }
10417         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10418         {
10419                 GL_BlendFunc(GL_ONE, GL_ONE);
10420                 GL_DepthMask(false);
10421         }
10422         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10423         {
10424                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10425                 GL_DepthMask(false);
10426         }
10427         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10428         {
10429                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10430                 GL_DepthMask(false);
10431         }
10432         else
10433         {
10434                 GL_BlendFunc(GL_ONE, GL_ZERO);
10435                 GL_DepthMask(writedepth);
10436         }
10437
10438         rsurface.lightmapcolor4f = NULL;
10439
10440         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10441         {
10442                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10443
10444                 rsurface.lightmapcolor4f = NULL;
10445                 rsurface.lightmapcolor4f_bufferobject = 0;
10446                 rsurface.lightmapcolor4f_bufferoffset = 0;
10447         }
10448         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10449         {
10450                 qboolean applycolor = true;
10451                 float one = 1.0;
10452
10453                 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10454
10455                 r_refdef.lightmapintensity = 1;
10456                 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
10457                 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10458         }
10459         else
10460         {
10461                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10462
10463                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10464                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10465                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10466         }
10467
10468         if(!rsurface.lightmapcolor4f)
10469                 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
10470
10471         RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
10472         RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
10473         if(r_refdef.fogenabled)
10474                 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
10475
10476         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10477         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10478 }
10479
10480 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10481 {
10482         CHECKGLERROR
10483         RSurf_SetupDepthAndCulling();
10484         if (r_showsurfaces.integer == 3 && !prepass)
10485         {
10486                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10487                 return;
10488         }
10489         switch (vid.renderpath)
10490         {
10491         case RENDERPATH_GL20:
10492         case RENDERPATH_CGGL:
10493                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10494                 break;
10495         case RENDERPATH_GL13:
10496                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10497                 break;
10498         case RENDERPATH_GL11:
10499                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10500                 break;
10501         }
10502         CHECKGLERROR
10503 }
10504
10505 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10506 {
10507         CHECKGLERROR
10508         RSurf_SetupDepthAndCulling();
10509         if (r_showsurfaces.integer == 3 && !prepass)
10510         {
10511                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10512                 return;
10513         }
10514         switch (vid.renderpath)
10515         {
10516         case RENDERPATH_GL20:
10517         case RENDERPATH_CGGL:
10518                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10519                 break;
10520         case RENDERPATH_GL13:
10521                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10522                 break;
10523         case RENDERPATH_GL11:
10524                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10525                 break;
10526         }
10527         CHECKGLERROR
10528 }
10529
10530 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10531 {
10532         int i, j;
10533         int texturenumsurfaces, endsurface;
10534         texture_t *texture;
10535         const msurface_t *surface;
10536         const msurface_t *texturesurfacelist[256];
10537
10538         // if the model is static it doesn't matter what value we give for
10539         // wantnormals and wanttangents, so this logic uses only rules applicable
10540         // to a model, knowing that they are meaningless otherwise
10541         if (ent == r_refdef.scene.worldentity)
10542                 RSurf_ActiveWorldEntity();
10543         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10544                 RSurf_ActiveModelEntity(ent, false, false, false);
10545         else
10546         {
10547                 switch (vid.renderpath)
10548                 {
10549                 case RENDERPATH_GL20:
10550                 case RENDERPATH_CGGL:
10551                         RSurf_ActiveModelEntity(ent, true, true, false);
10552                         break;
10553                 case RENDERPATH_GL13:
10554                 case RENDERPATH_GL11:
10555                         RSurf_ActiveModelEntity(ent, true, false, false);
10556                         break;
10557                 }
10558         }
10559
10560         if (r_transparentdepthmasking.integer)
10561         {
10562                 qboolean setup = false;
10563                 for (i = 0;i < numsurfaces;i = j)
10564                 {
10565                         j = i + 1;
10566                         surface = rsurface.modelsurfaces + surfacelist[i];
10567                         texture = surface->texture;
10568                         rsurface.texture = R_GetCurrentTexture(texture);
10569                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10570                         // scan ahead until we find a different texture
10571                         endsurface = min(i + 1024, numsurfaces);
10572                         texturenumsurfaces = 0;
10573                         texturesurfacelist[texturenumsurfaces++] = surface;
10574                         for (;j < endsurface;j++)
10575                         {
10576                                 surface = rsurface.modelsurfaces + surfacelist[j];
10577                                 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10578                                         break;
10579                                 texturesurfacelist[texturenumsurfaces++] = surface;
10580                         }
10581                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10582                                 continue;
10583                         // render the range of surfaces as depth
10584                         if (!setup)
10585                         {
10586                                 setup = true;
10587                                 GL_ColorMask(0,0,0,0);
10588                                 GL_Color(1,1,1,1);
10589                                 GL_DepthTest(true);
10590                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10591                                 GL_DepthMask(true);
10592                                 GL_AlphaTest(false);
10593                                 R_Mesh_ColorPointer(NULL, 0, 0);
10594                                 R_Mesh_ResetTextureState();
10595                                 R_SetupShader_DepthOrShadow();
10596                         }
10597                         RSurf_SetupDepthAndCulling();
10598                         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10599                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10600                 }
10601                 if (setup)
10602                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10603         }
10604
10605         for (i = 0;i < numsurfaces;i = j)
10606         {
10607                 j = i + 1;
10608                 surface = rsurface.modelsurfaces + surfacelist[i];
10609                 texture = surface->texture;
10610                 rsurface.texture = R_GetCurrentTexture(texture);
10611                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10612                 // scan ahead until we find a different texture
10613                 endsurface = min(i + 1024, numsurfaces);
10614                 texturenumsurfaces = 0;
10615                 texturesurfacelist[texturenumsurfaces++] = surface;
10616                 for (;j < endsurface;j++)
10617                 {
10618                         surface = rsurface.modelsurfaces + surfacelist[j];
10619                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10620                                 break;
10621                         texturesurfacelist[texturenumsurfaces++] = surface;
10622                 }
10623                 // render the range of surfaces
10624                 if (ent == r_refdef.scene.worldentity)
10625                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10626                 else
10627                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10628         }
10629         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10630         GL_AlphaTest(false);
10631 }
10632
10633 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10634 {
10635         // transparent surfaces get pushed off into the transparent queue
10636         int surfacelistindex;
10637         const msurface_t *surface;
10638         vec3_t tempcenter, center;
10639         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10640         {
10641                 surface = texturesurfacelist[surfacelistindex];
10642                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10643                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10644                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10645                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10646                 if (queueentity->transparent_offset) // transparent offset
10647                 {
10648                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10649                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10650                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10651                 }
10652                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10653         }
10654 }
10655
10656 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10657 {
10658         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10659         CHECKGLERROR
10660         if (depthonly)
10661         {
10662                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10663                         return;
10664                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10665                         return;
10666                 RSurf_SetupDepthAndCulling();
10667                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10668                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10669         }
10670         else if (prepass)
10671         {
10672                 if (!rsurface.texture->currentnumlayers)
10673                         return;
10674                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10675                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10676                 else
10677                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10678         }
10679         else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
10680         {
10681                 RSurf_SetupDepthAndCulling();
10682                 GL_AlphaTest(false);
10683                 R_Mesh_ColorPointer(NULL, 0, 0);
10684                 R_Mesh_ResetTextureState();
10685                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10686                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10687                 GL_DepthMask(true);
10688                 GL_BlendFunc(GL_ONE, GL_ZERO);
10689                 GL_Color(0, 0, 0, 1);
10690                 GL_DepthTest(writedepth);
10691                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10692         }
10693         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
10694         {
10695                 RSurf_SetupDepthAndCulling();
10696                 GL_AlphaTest(false);
10697                 R_Mesh_ColorPointer(NULL, 0, 0);
10698                 R_Mesh_ResetTextureState();
10699                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10700                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10701                 GL_DepthMask(true);
10702                 GL_BlendFunc(GL_ONE, GL_ZERO);
10703                 GL_DepthTest(true);
10704                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
10705         }
10706         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
10707                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10708         else if (!rsurface.texture->currentnumlayers)
10709                 return;
10710         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10711         {
10712                 // in the deferred case, transparent surfaces were queued during prepass
10713                 if (!r_shadow_usingdeferredprepass)
10714                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10715         }
10716         else
10717         {
10718                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10719                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10720         }
10721         CHECKGLERROR
10722 }
10723
10724 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10725 {
10726         int i, j;
10727         texture_t *texture;
10728         // break the surface list down into batches by texture and use of lightmapping
10729         for (i = 0;i < numsurfaces;i = j)
10730         {
10731                 j = i + 1;
10732                 // texture is the base texture pointer, rsurface.texture is the
10733                 // current frame/skin the texture is directing us to use (for example
10734                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10735                 // use skin 1 instead)
10736                 texture = surfacelist[i]->texture;
10737                 rsurface.texture = R_GetCurrentTexture(texture);
10738                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
10739                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10740                 {
10741                         // if this texture is not the kind we want, skip ahead to the next one
10742                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10743                                 ;
10744                         continue;
10745                 }
10746                 // simply scan ahead until we find a different texture or lightmap state
10747                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
10748                         ;
10749                 // render the range of surfaces
10750                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10751         }
10752 }
10753
10754 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10755 {
10756         CHECKGLERROR
10757         if (depthonly)
10758         {
10759                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10760                         return;
10761                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10762                         return;
10763                 RSurf_SetupDepthAndCulling();
10764                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10765                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10766         }
10767         else if (prepass)
10768         {
10769                 if (!rsurface.texture->currentnumlayers)
10770                         return;
10771                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10772                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10773                 else
10774                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10775         }
10776         else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
10777         {
10778                 RSurf_SetupDepthAndCulling();
10779                 GL_AlphaTest(false);
10780                 R_Mesh_ColorPointer(NULL, 0, 0);
10781                 R_Mesh_ResetTextureState();
10782                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10783                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10784                 GL_DepthMask(true);
10785                 GL_BlendFunc(GL_ONE, GL_ZERO);
10786                 GL_Color(0, 0, 0, 1);
10787                 GL_DepthTest(writedepth);
10788                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10789         }
10790         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10791         {
10792                 RSurf_SetupDepthAndCulling();
10793                 GL_AlphaTest(false);
10794                 R_Mesh_ColorPointer(NULL, 0, 0);
10795                 R_Mesh_ResetTextureState();
10796                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10797                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10798                 GL_DepthMask(true);
10799                 GL_BlendFunc(GL_ONE, GL_ZERO);
10800                 GL_DepthTest(true);
10801                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
10802         }
10803         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
10804                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10805         else if (!rsurface.texture->currentnumlayers)
10806                 return;
10807         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10808         {
10809                 // in the deferred case, transparent surfaces were queued during prepass
10810                 if (!r_shadow_usingdeferredprepass)
10811                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10812         }
10813         else
10814         {
10815                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10816                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10817         }
10818         CHECKGLERROR
10819 }
10820
10821 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10822 {
10823         int i, j;
10824         texture_t *texture;
10825         // break the surface list down into batches by texture and use of lightmapping
10826         for (i = 0;i < numsurfaces;i = j)
10827         {
10828                 j = i + 1;
10829                 // texture is the base texture pointer, rsurface.texture is the
10830                 // current frame/skin the texture is directing us to use (for example
10831                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10832                 // use skin 1 instead)
10833                 texture = surfacelist[i]->texture;
10834                 rsurface.texture = R_GetCurrentTexture(texture);
10835                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
10836                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10837                 {
10838                         // if this texture is not the kind we want, skip ahead to the next one
10839                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10840                                 ;
10841                         continue;
10842                 }
10843                 // simply scan ahead until we find a different texture or lightmap state
10844                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
10845                         ;
10846                 // render the range of surfaces
10847                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10848         }
10849 }
10850
10851 float locboxvertex3f[6*4*3] =
10852 {
10853         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10854         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10855         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10856         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10857         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10858         1,0,0, 0,0,0, 0,1,0, 1,1,0
10859 };
10860
10861 unsigned short locboxelements[6*2*3] =
10862 {
10863          0, 1, 2, 0, 2, 3,
10864          4, 5, 6, 4, 6, 7,
10865          8, 9,10, 8,10,11,
10866         12,13,14, 12,14,15,
10867         16,17,18, 16,18,19,
10868         20,21,22, 20,22,23
10869 };
10870
10871 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10872 {
10873         int i, j;
10874         cl_locnode_t *loc = (cl_locnode_t *)ent;
10875         vec3_t mins, size;
10876         float vertex3f[6*4*3];
10877         CHECKGLERROR
10878         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10879         GL_DepthMask(false);
10880         GL_DepthRange(0, 1);
10881         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10882         GL_DepthTest(true);
10883         GL_CullFace(GL_NONE);
10884         R_EntityMatrix(&identitymatrix);
10885
10886         R_Mesh_VertexPointer(vertex3f, 0, 0);
10887         R_Mesh_ColorPointer(NULL, 0, 0);
10888         R_Mesh_ResetTextureState();
10889         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10890
10891         i = surfacelist[0];
10892         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10893                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10894                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10895                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10896
10897         if (VectorCompare(loc->mins, loc->maxs))
10898         {
10899                 VectorSet(size, 2, 2, 2);
10900                 VectorMA(loc->mins, -0.5f, size, mins);
10901         }
10902         else
10903         {
10904                 VectorCopy(loc->mins, mins);
10905                 VectorSubtract(loc->maxs, loc->mins, size);
10906         }
10907
10908         for (i = 0;i < 6*4*3;)
10909                 for (j = 0;j < 3;j++, i++)
10910                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10911
10912         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
10913 }
10914
10915 void R_DrawLocs(void)
10916 {
10917         int index;
10918         cl_locnode_t *loc, *nearestloc;
10919         vec3_t center;
10920         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10921         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10922         {
10923                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10924                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10925         }
10926 }
10927
10928 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10929 {
10930         if (decalsystem->decals)
10931                 Mem_Free(decalsystem->decals);
10932         memset(decalsystem, 0, sizeof(*decalsystem));
10933 }
10934
10935 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)
10936 {
10937         tridecal_t *decal;
10938         tridecal_t *decals;
10939         int i;
10940         int maxdecals;
10941
10942         // expand or initialize the system
10943         if (decalsystem->maxdecals <= decalsystem->numdecals)
10944         {
10945                 decalsystem_t old = *decalsystem;
10946                 qboolean useshortelements;
10947                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10948                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10949                 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)));
10950                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10951                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10952                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10953                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10954                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10955                 if (decalsystem->numdecals)
10956                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10957                 if (old.decals)
10958                         Mem_Free(old.decals);
10959                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10960                         decalsystem->element3i[i] = i;
10961                 if (useshortelements)
10962                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10963                                 decalsystem->element3s[i] = i;
10964         }
10965
10966         // grab a decal and search for another free slot for the next one
10967         maxdecals = decalsystem->maxdecals;
10968         decals = decalsystem->decals;
10969         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10970         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
10971                 ;
10972         decalsystem->freedecal = i;
10973         if (decalsystem->numdecals <= i)
10974                 decalsystem->numdecals = i + 1;
10975
10976         // initialize the decal
10977         decal->lived = 0;
10978         decal->triangleindex = triangleindex;
10979         decal->surfaceindex = surfaceindex;
10980         decal->decalsequence = decalsequence;
10981         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
10982         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
10983         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
10984         decal->color4ub[0][3] = 255;
10985         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
10986         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
10987         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
10988         decal->color4ub[1][3] = 255;
10989         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
10990         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
10991         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
10992         decal->color4ub[2][3] = 255;
10993         decal->vertex3f[0][0] = v0[0];
10994         decal->vertex3f[0][1] = v0[1];
10995         decal->vertex3f[0][2] = v0[2];
10996         decal->vertex3f[1][0] = v1[0];
10997         decal->vertex3f[1][1] = v1[1];
10998         decal->vertex3f[1][2] = v1[2];
10999         decal->vertex3f[2][0] = v2[0];
11000         decal->vertex3f[2][1] = v2[1];
11001         decal->vertex3f[2][2] = v2[2];
11002         decal->texcoord2f[0][0] = t0[0];
11003         decal->texcoord2f[0][1] = t0[1];
11004         decal->texcoord2f[1][0] = t1[0];
11005         decal->texcoord2f[1][1] = t1[1];
11006         decal->texcoord2f[2][0] = t2[0];
11007         decal->texcoord2f[2][1] = t2[1];
11008 }
11009
11010 extern cvar_t cl_decals_bias;
11011 extern cvar_t cl_decals_models;
11012 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11013 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)
11014 {
11015         matrix4x4_t projection;
11016         decalsystem_t *decalsystem;
11017         qboolean dynamic;
11018         dp_model_t *model;
11019         const float *vertex3f;
11020         const msurface_t *surface;
11021         const msurface_t *surfaces;
11022         const int *surfacelist;
11023         const texture_t *texture;
11024         int numvertices;
11025         int numtriangles;
11026         int numsurfacelist;
11027         int surfacelistindex;
11028         int surfaceindex;
11029         int triangleindex;
11030         int decalsurfaceindex;
11031         int cornerindex;
11032         int index;
11033         int numpoints;
11034         const int *e;
11035         float localorigin[3];
11036         float localnormal[3];
11037         float localmins[3];
11038         float localmaxs[3];
11039         float localsize;
11040         float ilocalsize;
11041         float v[9][3];
11042         float tc[9][2];
11043         float c[9][4];
11044         //float normal[3];
11045         float planes[6][4];
11046         float f;
11047         float points[2][9][3];
11048         float angles[3];
11049         float temp[3];
11050
11051         decalsystem = &ent->decalsystem;
11052         model = ent->model;
11053         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11054         {
11055                 R_DecalSystem_Reset(&ent->decalsystem);
11056                 return;
11057         }
11058
11059         if (!model->brush.data_nodes && !cl_decals_models.integer)
11060         {
11061                 if (decalsystem->model)
11062                         R_DecalSystem_Reset(decalsystem);
11063                 return;
11064         }
11065
11066         if (decalsystem->model != model)
11067                 R_DecalSystem_Reset(decalsystem);
11068         decalsystem->model = model;
11069
11070         RSurf_ActiveModelEntity(ent, false, false, false);
11071
11072         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11073         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11074         VectorNormalize(localnormal);
11075         localsize = worldsize*rsurface.inversematrixscale;
11076         ilocalsize = 1.0f / localsize;
11077         localmins[0] = localorigin[0] - localsize;
11078         localmins[1] = localorigin[1] - localsize;
11079         localmins[2] = localorigin[2] - localsize;
11080         localmaxs[0] = localorigin[0] + localsize;
11081         localmaxs[1] = localorigin[1] + localsize;
11082         localmaxs[2] = localorigin[2] + localsize;
11083
11084         //VectorCopy(localnormal, planes[4]);
11085         //VectorVectors(planes[4], planes[2], planes[0]);
11086         AnglesFromVectors(angles, localnormal, NULL, false);
11087         AngleVectors(angles, planes[0], planes[2], planes[4]);
11088         VectorNegate(planes[0], planes[1]);
11089         VectorNegate(planes[2], planes[3]);
11090         VectorNegate(planes[4], planes[5]);
11091         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11092         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11093         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11094         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11095         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11096         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11097
11098 #if 1
11099 // works
11100 {
11101         matrix4x4_t forwardprojection;
11102         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11103         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11104 }
11105 #else
11106 // broken
11107 {
11108         float projectionvector[4][3];
11109         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11110         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11111         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11112         projectionvector[0][0] = planes[0][0] * ilocalsize;
11113         projectionvector[0][1] = planes[1][0] * ilocalsize;
11114         projectionvector[0][2] = planes[2][0] * ilocalsize;
11115         projectionvector[1][0] = planes[0][1] * ilocalsize;
11116         projectionvector[1][1] = planes[1][1] * ilocalsize;
11117         projectionvector[1][2] = planes[2][1] * ilocalsize;
11118         projectionvector[2][0] = planes[0][2] * ilocalsize;
11119         projectionvector[2][1] = planes[1][2] * ilocalsize;
11120         projectionvector[2][2] = planes[2][2] * ilocalsize;
11121         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11122         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11123         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11124         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11125 }
11126 #endif
11127
11128         dynamic = model->surfmesh.isanimated;
11129         vertex3f = rsurface.modelvertex3f;
11130         numsurfacelist = model->nummodelsurfaces;
11131         surfacelist = model->sortedmodelsurfaces;
11132         surfaces = model->data_surfaces;
11133         for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11134         {
11135                 surfaceindex = surfacelist[surfacelistindex];
11136                 surface = surfaces + surfaceindex;
11137                 // skip transparent surfaces
11138                 texture = surface->texture;
11139                 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11140                         continue;
11141                 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11142                         continue;
11143                 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11144                         continue;
11145                 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
11146                 numvertices = surface->num_vertices;
11147                 numtriangles = surface->num_triangles;
11148                 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
11149                 {
11150                         for (cornerindex = 0;cornerindex < 3;cornerindex++)
11151                         {
11152                                 index = 3*e[cornerindex];
11153                                 VectorCopy(vertex3f + index, v[cornerindex]);
11154                         }
11155                         // cull backfaces
11156                         //TriangleNormal(v[0], v[1], v[2], normal);
11157                         //if (DotProduct(normal, localnormal) < 0.0f)
11158                         //      continue;
11159                         // clip by each of the box planes formed from the projection matrix
11160                         // if anything survives, we emit the decal
11161                         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]);
11162                         if (numpoints < 3)
11163                                 continue;
11164                         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]);
11165                         if (numpoints < 3)
11166                                 continue;
11167                         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]);
11168                         if (numpoints < 3)
11169                                 continue;
11170                         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]);
11171                         if (numpoints < 3)
11172                                 continue;
11173                         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]);
11174                         if (numpoints < 3)
11175                                 continue;
11176                         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]);
11177                         if (numpoints < 3)
11178                                 continue;
11179                         // some part of the triangle survived, so we have to accept it...
11180                         if (dynamic)
11181                         {
11182                                 // dynamic always uses the original triangle
11183                                 numpoints = 3;
11184                                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11185                                 {
11186                                         index = 3*e[cornerindex];
11187                                         VectorCopy(vertex3f + index, v[cornerindex]);
11188                                 }
11189                         }
11190                         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11191                         {
11192                                 // convert vertex positions to texcoords
11193                                 Matrix4x4_Transform(&projection, v[cornerindex], temp);
11194                                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11195                                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11196                                 // calculate distance fade from the projection origin
11197                                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11198                                 f = bound(0.0f, f, 1.0f);
11199                                 c[cornerindex][0] = r * f;
11200                                 c[cornerindex][1] = g * f;
11201                                 c[cornerindex][2] = b * f;
11202                                 c[cornerindex][3] = 1.0f;
11203                                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11204                         }
11205                         if (dynamic)
11206                                 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);
11207                         else
11208                                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11209                                         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);
11210                 }
11211         }
11212 }
11213
11214 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11215 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)
11216 {
11217         int renderentityindex;
11218         float worldmins[3];
11219         float worldmaxs[3];
11220         entity_render_t *ent;
11221
11222         if (!cl_decals_newsystem.integer)
11223                 return;
11224
11225         worldmins[0] = worldorigin[0] - worldsize;
11226         worldmins[1] = worldorigin[1] - worldsize;
11227         worldmins[2] = worldorigin[2] - worldsize;
11228         worldmaxs[0] = worldorigin[0] + worldsize;
11229         worldmaxs[1] = worldorigin[1] + worldsize;
11230         worldmaxs[2] = worldorigin[2] + worldsize;
11231
11232         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11233
11234         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11235         {
11236                 ent = r_refdef.scene.entities[renderentityindex];
11237                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11238                         continue;
11239
11240                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11241         }
11242 }
11243
11244 typedef struct r_decalsystem_splatqueue_s
11245 {
11246         vec3_t worldorigin;
11247         vec3_t worldnormal;
11248         float color[4];
11249         float tcrange[4];
11250         float worldsize;
11251         int decalsequence;
11252 }
11253 r_decalsystem_splatqueue_t;
11254
11255 int r_decalsystem_numqueued = 0;
11256 #define MAX_DECALSYSTEM_QUEUE 1024
11257 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11258
11259 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)
11260 {
11261         r_decalsystem_splatqueue_t *queue;
11262
11263         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11264                 return;
11265
11266         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11267         VectorCopy(worldorigin, queue->worldorigin);
11268         VectorCopy(worldnormal, queue->worldnormal);
11269         Vector4Set(queue->color, r, g, b, a);
11270         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11271         queue->worldsize = worldsize;
11272         queue->decalsequence = cl.decalsequence++;
11273 }
11274
11275 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11276 {
11277         int i;
11278         r_decalsystem_splatqueue_t *queue;
11279
11280         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11281                 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);
11282         r_decalsystem_numqueued = 0;
11283 }
11284
11285 extern cvar_t cl_decals_max;
11286 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11287 {
11288         int i;
11289         decalsystem_t *decalsystem = &ent->decalsystem;
11290         int numdecals;
11291         int killsequence;
11292         tridecal_t *decal;
11293         float frametime;
11294         float lifetime;
11295
11296         if (!decalsystem->numdecals)
11297                 return;
11298
11299         if (r_showsurfaces.integer)
11300                 return;
11301
11302         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11303         {
11304                 R_DecalSystem_Reset(decalsystem);
11305                 return;
11306         }
11307
11308         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11309         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11310
11311         if (decalsystem->lastupdatetime)
11312                 frametime = (cl.time - decalsystem->lastupdatetime);
11313         else
11314                 frametime = 0;
11315         decalsystem->lastupdatetime = cl.time;
11316         decal = decalsystem->decals;
11317         numdecals = decalsystem->numdecals;
11318
11319         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11320         {
11321                 if (decal->color4ub[0][3])
11322                 {
11323                         decal->lived += frametime;
11324                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11325                         {
11326                                 memset(decal, 0, sizeof(*decal));
11327                                 if (decalsystem->freedecal > i)
11328                                         decalsystem->freedecal = i;
11329                         }
11330                 }
11331         }
11332         decal = decalsystem->decals;
11333         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
11334                 numdecals--;
11335
11336         // collapse the array by shuffling the tail decals into the gaps
11337         for (;;)
11338         {
11339                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
11340                         decalsystem->freedecal++;
11341                 if (decalsystem->freedecal == numdecals)
11342                         break;
11343                 decal[decalsystem->freedecal] = decal[--numdecals];
11344         }
11345
11346         decalsystem->numdecals = numdecals;
11347
11348         if (numdecals <= 0)
11349         {
11350                 // if there are no decals left, reset decalsystem
11351                 R_DecalSystem_Reset(decalsystem);
11352         }
11353 }
11354
11355 extern skinframe_t *decalskinframe;
11356 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11357 {
11358         int i;
11359         decalsystem_t *decalsystem = &ent->decalsystem;
11360         int numdecals;
11361         tridecal_t *decal;
11362         float fadedelay;
11363         float faderate;
11364         float alpha;
11365         float *v3f;
11366         float *c4f;
11367         float *t2f;
11368         const int *e;
11369         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11370         int numtris = 0;
11371
11372         numdecals = decalsystem->numdecals;
11373         if (!numdecals)
11374                 return;
11375
11376         if (r_showsurfaces.integer)
11377                 return;
11378
11379         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11380         {
11381                 R_DecalSystem_Reset(decalsystem);
11382                 return;
11383         }
11384
11385         // if the model is static it doesn't matter what value we give for
11386         // wantnormals and wanttangents, so this logic uses only rules applicable
11387         // to a model, knowing that they are meaningless otherwise
11388         if (ent == r_refdef.scene.worldentity)
11389                 RSurf_ActiveWorldEntity();
11390         else
11391                 RSurf_ActiveModelEntity(ent, false, false, false);
11392
11393         decalsystem->lastupdatetime = cl.time;
11394         decal = decalsystem->decals;
11395
11396         fadedelay = cl_decals_time.value;
11397         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11398
11399         // update vertex positions for animated models
11400         v3f = decalsystem->vertex3f;
11401         c4f = decalsystem->color4f;
11402         t2f = decalsystem->texcoord2f;
11403         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11404         {
11405                 if (!decal->color4ub[0][3])
11406                         continue;
11407
11408                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11409                         continue;
11410
11411                 // update color values for fading decals
11412                 if (decal->lived >= cl_decals_time.value)
11413                 {
11414                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11415                         alpha *= (1.0f/255.0f);
11416                 }
11417                 else
11418                         alpha = 1.0f/255.0f;
11419
11420                 c4f[ 0] = decal->color4ub[0][0] * alpha;
11421                 c4f[ 1] = decal->color4ub[0][1] * alpha;
11422                 c4f[ 2] = decal->color4ub[0][2] * alpha;
11423                 c4f[ 3] = 1;
11424                 c4f[ 4] = decal->color4ub[1][0] * alpha;
11425                 c4f[ 5] = decal->color4ub[1][1] * alpha;
11426                 c4f[ 6] = decal->color4ub[1][2] * alpha;
11427                 c4f[ 7] = 1;
11428                 c4f[ 8] = decal->color4ub[2][0] * alpha;
11429                 c4f[ 9] = decal->color4ub[2][1] * alpha;
11430                 c4f[10] = decal->color4ub[2][2] * alpha;
11431                 c4f[11] = 1;
11432
11433                 t2f[0] = decal->texcoord2f[0][0];
11434                 t2f[1] = decal->texcoord2f[0][1];
11435                 t2f[2] = decal->texcoord2f[1][0];
11436                 t2f[3] = decal->texcoord2f[1][1];
11437                 t2f[4] = decal->texcoord2f[2][0];
11438                 t2f[5] = decal->texcoord2f[2][1];
11439
11440                 // update vertex positions for animated models
11441                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
11442                 {
11443                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11444                         VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
11445                         VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
11446                         VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
11447                 }
11448                 else
11449                 {
11450                         VectorCopy(decal->vertex3f[0], v3f);
11451                         VectorCopy(decal->vertex3f[1], v3f + 3);
11452                         VectorCopy(decal->vertex3f[2], v3f + 6);
11453                 }
11454
11455                 v3f += 9;
11456                 c4f += 12;
11457                 t2f += 6;
11458                 numtris++;
11459         }
11460
11461         if (numtris > 0)
11462         {
11463                 r_refdef.stats.drawndecals += numtris;
11464
11465                 if (r_refdef.fogenabled)
11466                 {
11467                         switch(vid.renderpath)
11468                         {
11469                         case RENDERPATH_GL20:
11470                         case RENDERPATH_CGGL:
11471                         case RENDERPATH_GL13:
11472                         case RENDERPATH_GL11:
11473                                 for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
11474                                 {
11475                                         alpha = RSurf_FogVertex(v3f);
11476                                         c4f[0] *= alpha;
11477                                         c4f[1] *= alpha;
11478                                         c4f[2] *= alpha;
11479                                 }
11480                                 break;
11481                         }
11482                 }
11483
11484                 // now render the decals all at once
11485                 // (this assumes they all use one particle font texture!)
11486                 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);
11487                 R_Mesh_ResetTextureState();
11488                 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
11489                 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
11490                 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
11491                 GL_DepthMask(false);
11492                 GL_DepthRange(0, 1);
11493                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11494                 GL_DepthTest(true);
11495                 GL_CullFace(GL_NONE);
11496                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11497                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
11498                 GL_LockArrays(0, numtris * 3);
11499                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
11500                 GL_LockArrays(0, 0);
11501         }
11502 }
11503
11504 static void R_DrawModelDecals(void)
11505 {
11506         int i, numdecals;
11507
11508         // fade faster when there are too many decals
11509         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11510         for (i = 0;i < r_refdef.scene.numentities;i++)
11511                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11512
11513         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11514         for (i = 0;i < r_refdef.scene.numentities;i++)
11515                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11516                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11517
11518         R_DecalSystem_ApplySplatEntitiesQueue();
11519
11520         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11521         for (i = 0;i < r_refdef.scene.numentities;i++)
11522                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11523
11524         r_refdef.stats.totaldecals += numdecals;
11525
11526         if (r_showsurfaces.integer)
11527                 return;
11528
11529         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11530
11531         for (i = 0;i < r_refdef.scene.numentities;i++)
11532         {
11533                 if (!r_refdef.viewcache.entityvisible[i])
11534                         continue;
11535                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11536                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11537         }
11538 }
11539
11540 void R_DrawDebugModel(void)
11541 {
11542         entity_render_t *ent = rsurface.entity;
11543         int i, j, k, l, flagsmask;
11544         const int *elements;
11545         q3mbrush_t *brush;
11546         const msurface_t *surface;
11547         dp_model_t *model = ent->model;
11548         vec3_t v;
11549
11550         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11551
11552         R_Mesh_ColorPointer(NULL, 0, 0);
11553         R_Mesh_ResetTextureState();
11554         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11555         GL_DepthRange(0, 1);
11556         GL_DepthTest(!r_showdisabledepthtest.integer);
11557         GL_DepthMask(false);
11558         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11559
11560         if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
11561         {
11562                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11563                 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
11564                 {
11565                         if (brush->colbrushf && brush->colbrushf->numtriangles)
11566                         {
11567                                 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
11568                                 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);
11569                                 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
11570                         }
11571                 }
11572                 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
11573                 {
11574                         if (surface->num_collisiontriangles)
11575                         {
11576                                 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
11577                                 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);
11578                                 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
11579                         }
11580                 }
11581         }
11582
11583         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11584
11585         if (r_showtris.integer || r_shownormals.integer)
11586         {
11587                 if (r_showdisabledepthtest.integer)
11588                 {
11589                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11590                         GL_DepthMask(false);
11591                 }
11592                 else
11593                 {
11594                         GL_BlendFunc(GL_ONE, GL_ZERO);
11595                         GL_DepthMask(true);
11596                 }
11597                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11598                 {
11599                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11600                                 continue;
11601                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11602                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11603                         {
11604                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
11605                                 if (r_showtris.value > 0)
11606                                 {
11607                                         if (!rsurface.texture->currentlayers->depthmask)
11608                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11609                                         else if (ent == r_refdef.scene.worldentity)
11610                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11611                                         else
11612                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11613                                         elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
11614                                         R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
11615                                         R_Mesh_ColorPointer(NULL, 0, 0);
11616                                         R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
11617                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11618                                         //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
11619                                         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);
11620                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11621                                         CHECKGLERROR
11622                                 }
11623                                 if (r_shownormals.value < 0)
11624                                 {
11625                                         qglBegin(GL_LINES);
11626                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11627                                         {
11628                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11629                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11630                                                 qglVertex3f(v[0], v[1], v[2]);
11631                                                 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
11632                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11633                                                 qglVertex3f(v[0], v[1], v[2]);
11634                                         }
11635                                         qglEnd();
11636                                         CHECKGLERROR
11637                                 }
11638                                 if (r_shownormals.value > 0)
11639                                 {
11640                                         qglBegin(GL_LINES);
11641                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11642                                         {
11643                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11644                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11645                                                 qglVertex3f(v[0], v[1], v[2]);
11646                                                 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
11647                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11648                                                 qglVertex3f(v[0], v[1], v[2]);
11649                                         }
11650                                         qglEnd();
11651                                         CHECKGLERROR
11652                                         qglBegin(GL_LINES);
11653                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11654                                         {
11655                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11656                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11657                                                 qglVertex3f(v[0], v[1], v[2]);
11658                                                 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
11659                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11660                                                 qglVertex3f(v[0], v[1], v[2]);
11661                                         }
11662                                         qglEnd();
11663                                         CHECKGLERROR
11664                                         qglBegin(GL_LINES);
11665                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11666                                         {
11667                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11668                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11669                                                 qglVertex3f(v[0], v[1], v[2]);
11670                                                 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
11671                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11672                                                 qglVertex3f(v[0], v[1], v[2]);
11673                                         }
11674                                         qglEnd();
11675                                         CHECKGLERROR
11676                                 }
11677                         }
11678                 }
11679                 rsurface.texture = NULL;
11680         }
11681 }
11682
11683 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11684 int r_maxsurfacelist = 0;
11685 const msurface_t **r_surfacelist = NULL;
11686 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11687 {
11688         int i, j, endj, f, flagsmask;
11689         texture_t *t;
11690         dp_model_t *model = r_refdef.scene.worldmodel;
11691         msurface_t *surfaces;
11692         unsigned char *update;
11693         int numsurfacelist = 0;
11694         if (model == NULL)
11695                 return;
11696
11697         if (r_maxsurfacelist < model->num_surfaces)
11698         {
11699                 r_maxsurfacelist = model->num_surfaces;
11700                 if (r_surfacelist)
11701                         Mem_Free((msurface_t**)r_surfacelist);
11702                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11703         }
11704
11705         RSurf_ActiveWorldEntity();
11706
11707         surfaces = model->data_surfaces;
11708         update = model->brushq1.lightmapupdateflags;
11709
11710         // update light styles on this submodel
11711         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11712         {
11713                 model_brush_lightstyleinfo_t *style;
11714                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11715                 {
11716                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11717                         {
11718                                 int *list = style->surfacelist;
11719                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11720                                 for (j = 0;j < style->numsurfaces;j++)
11721                                         update[list[j]] = true;
11722                         }
11723                 }
11724         }
11725
11726         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11727
11728         if (debug)
11729         {
11730                 R_DrawDebugModel();
11731                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11732                 return;
11733         }
11734
11735         f = 0;
11736         t = NULL;
11737         rsurface.uselightmaptexture = false;
11738         rsurface.texture = NULL;
11739         rsurface.rtlight = NULL;
11740         numsurfacelist = 0;
11741         // add visible surfaces to draw list
11742         for (i = 0;i < model->nummodelsurfaces;i++)
11743         {
11744                 j = model->sortedmodelsurfaces[i];
11745                 if (r_refdef.viewcache.world_surfacevisible[j])
11746                         r_surfacelist[numsurfacelist++] = surfaces + j;
11747         }
11748         // update lightmaps if needed
11749         if (update)
11750         {
11751                 int updated = 0;
11752                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11753                 {
11754                         if (r_refdef.viewcache.world_surfacevisible[j])
11755                         {
11756                                 if (update[j])
11757                                 {
11758                                         updated++;
11759                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11760                                 }
11761                         }
11762                 }
11763                 if (updated)
11764                 {
11765                         int count = model->brushq3.num_mergedlightmaps;
11766                         for (i = 0;i < count;i++)
11767                         {
11768                                 if (model->brushq3.data_deluxemaps[i])
11769                                         R_FlushTexture(model->brushq3.data_deluxemaps[i]);
11770                                 if (model->brushq3.data_lightmaps[i])
11771                                         R_FlushTexture(model->brushq3.data_lightmaps[i]);
11772                         }
11773                 }
11774         }
11775         // don't do anything if there were no surfaces
11776         if (!numsurfacelist)
11777         {
11778                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11779                 return;
11780         }
11781         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11782         GL_AlphaTest(false);
11783
11784         // add to stats if desired
11785         if (r_speeds.integer && !skysurfaces && !depthonly)
11786         {
11787                 r_refdef.stats.world_surfaces += numsurfacelist;
11788                 for (j = 0;j < numsurfacelist;j++)
11789                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11790         }
11791
11792         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11793 }
11794
11795 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11796 {
11797         int i, j, endj, f, flagsmask;
11798         texture_t *t;
11799         dp_model_t *model = ent->model;
11800         msurface_t *surfaces;
11801         unsigned char *update;
11802         int numsurfacelist = 0;
11803         if (model == NULL)
11804                 return;
11805
11806         if (r_maxsurfacelist < model->num_surfaces)
11807         {
11808                 r_maxsurfacelist = model->num_surfaces;
11809                 if (r_surfacelist)
11810                         Mem_Free((msurface_t **)r_surfacelist);
11811                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11812         }
11813
11814         // if the model is static it doesn't matter what value we give for
11815         // wantnormals and wanttangents, so this logic uses only rules applicable
11816         // to a model, knowing that they are meaningless otherwise
11817         if (ent == r_refdef.scene.worldentity)
11818                 RSurf_ActiveWorldEntity();
11819         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11820                 RSurf_ActiveModelEntity(ent, false, false, false);
11821         else if (prepass)
11822                 RSurf_ActiveModelEntity(ent, true, true, true);
11823         else if (depthonly)
11824                 RSurf_ActiveModelEntity(ent, false, false, false);
11825         else
11826         {
11827                 switch (vid.renderpath)
11828                 {
11829                 case RENDERPATH_GL20:
11830                 case RENDERPATH_CGGL:
11831                         RSurf_ActiveModelEntity(ent, true, true, false);
11832                         break;
11833                 case RENDERPATH_GL13:
11834                 case RENDERPATH_GL11:
11835                         RSurf_ActiveModelEntity(ent, true, false, false);
11836                         break;
11837                 }
11838         }
11839
11840         surfaces = model->data_surfaces;
11841         update = model->brushq1.lightmapupdateflags;
11842
11843         // update light styles
11844         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11845         {
11846                 model_brush_lightstyleinfo_t *style;
11847                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11848                 {
11849                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11850                         {
11851                                 int *list = style->surfacelist;
11852                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11853                                 for (j = 0;j < style->numsurfaces;j++)
11854                                         update[list[j]] = true;
11855                         }
11856                 }
11857         }
11858
11859         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11860
11861         if (debug)
11862         {
11863                 R_DrawDebugModel();
11864                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11865                 return;
11866         }
11867
11868         f = 0;
11869         t = NULL;
11870         rsurface.uselightmaptexture = false;
11871         rsurface.texture = NULL;
11872         rsurface.rtlight = NULL;
11873         numsurfacelist = 0;
11874         // add visible surfaces to draw list
11875         for (i = 0;i < model->nummodelsurfaces;i++)
11876                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11877         // don't do anything if there were no surfaces
11878         if (!numsurfacelist)
11879         {
11880                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11881                 return;
11882         }
11883         // update lightmaps if needed
11884         if (update)
11885         {
11886                 int updated = 0;
11887                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11888                 {
11889                         if (update[j])
11890                         {
11891                                 updated++;
11892                                 R_BuildLightMap(ent, surfaces + j);
11893                         }
11894                 }
11895                 if (updated)
11896                 {
11897                         int count = model->brushq3.num_mergedlightmaps;
11898                         for (i = 0;i < count;i++)
11899                         {
11900                                 if (model->brushq3.data_deluxemaps[i])
11901                                         R_FlushTexture(model->brushq3.data_deluxemaps[i]);
11902                                 if (model->brushq3.data_lightmaps[i])
11903                                         R_FlushTexture(model->brushq3.data_lightmaps[i]);
11904                         }
11905                 }
11906         }
11907         if (update)
11908                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11909                         if (update[j])
11910                                 R_BuildLightMap(ent, surfaces + j);
11911         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11912         GL_AlphaTest(false);
11913
11914         // add to stats if desired
11915         if (r_speeds.integer && !skysurfaces && !depthonly)
11916         {
11917                 r_refdef.stats.entities_surfaces += numsurfacelist;
11918                 for (j = 0;j < numsurfacelist;j++)
11919                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11920         }
11921
11922         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11923 }
11924
11925 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11926 {
11927         static texture_t texture;
11928         static msurface_t surface;
11929         const msurface_t *surfacelist = &surface;
11930
11931         // fake enough texture and surface state to render this geometry
11932
11933         texture.update_lastrenderframe = -1; // regenerate this texture
11934         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11935         texture.currentskinframe = skinframe;
11936         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11937         texture.specularscalemod = 1;
11938         texture.specularpowermod = 1;
11939
11940         surface.texture = &texture;
11941         surface.num_triangles = numtriangles;
11942         surface.num_firsttriangle = firsttriangle;
11943         surface.num_vertices = numvertices;
11944         surface.num_firstvertex = firstvertex;
11945
11946         // now render it
11947         rsurface.texture = R_GetCurrentTexture(surface.texture);
11948         rsurface.uselightmaptexture = false;
11949         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11950 }
11951
11952 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)
11953 {
11954         static msurface_t surface;
11955         const msurface_t *surfacelist = &surface;
11956
11957         // fake enough texture and surface state to render this geometry
11958
11959         surface.texture = texture;
11960         surface.num_triangles = numtriangles;
11961         surface.num_firsttriangle = firsttriangle;
11962         surface.num_vertices = numvertices;
11963         surface.num_firstvertex = firstvertex;
11964
11965         // now render it
11966         rsurface.texture = R_GetCurrentTexture(surface.texture);
11967         rsurface.uselightmaptexture = false;
11968         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11969 }