]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
only clear depth buffer bit for shadowmaps
[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_textureframe = 0; ///< used only by R_GetCurrentTexture
33
34 static qboolean r_loadnormalmap;
35 static qboolean r_loadgloss;
36 qboolean r_loadfog;
37 static qboolean r_loaddds;
38 static qboolean r_savedds;
39
40 //
41 // screen size info
42 //
43 r_refdef_t r_refdef;
44
45 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
46 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
47 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
48 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
49 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)"};
50 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
51 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
52 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
53
54 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
55 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"};
56 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
57 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)"};
58 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
59
60 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"};
61 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
62 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
63 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
64 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
65 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
66 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)"};
67 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
68 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
69 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"};
70 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"};
71 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
72 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"};
73 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"};
74 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"};
75 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
76 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
77 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
78 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
79 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)"};
80 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)"};
81 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
82 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
83 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
84 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
85 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
86 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
87 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
88 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."};
89 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
90 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
91 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
92 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."};
93 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
94 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
95 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"};
96 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"};
97 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
98 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
99 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
100 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
101 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"};
102
103 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
104 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
105 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
106 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
107 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
108 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
109 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
110 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
111
112 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
113 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
114
115 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
116 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
117 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
118
119 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)"};
120 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
121 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
122 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
123 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
124 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)"};
125 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)"};
126 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)"};
127 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)"};
128
129 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)"};
130 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
131 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"};
132 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
133 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
134
135 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
136 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
137 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
138 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
139
140 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
141 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
142 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
143 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
144 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
145 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
146 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
147
148 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
149 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
150 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
151 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)"};
152
153 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"};
154
155 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"};
156
157 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
158
159 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
160 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
161 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"};
162 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
163 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
164 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
165 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
166
167 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)"};
168
169 extern cvar_t v_glslgamma;
170
171 extern qboolean v_flipped_state;
172
173 static struct r_bloomstate_s
174 {
175         qboolean enabled;
176         qboolean hdr;
177
178         int bloomwidth, bloomheight;
179
180         int screentexturewidth, screentextureheight;
181         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
182
183         int bloomtexturewidth, bloomtextureheight;
184         rtexture_t *texture_bloom;
185
186         // arrays for rendering the screen passes
187         float screentexcoord2f[8];
188         float bloomtexcoord2f[8];
189         float offsettexcoord2f[8];
190
191         r_viewport_t viewport;
192 }
193 r_bloomstate;
194
195 r_waterstate_t r_waterstate;
196
197 /// shadow volume bsp struct with automatically growing nodes buffer
198 svbsp_t r_svbsp;
199
200 rtexture_t *r_texture_blanknormalmap;
201 rtexture_t *r_texture_white;
202 rtexture_t *r_texture_grey128;
203 rtexture_t *r_texture_black;
204 rtexture_t *r_texture_notexture;
205 rtexture_t *r_texture_whitecube;
206 rtexture_t *r_texture_normalizationcube;
207 rtexture_t *r_texture_fogattenuation;
208 rtexture_t *r_texture_gammaramps;
209 unsigned int r_texture_gammaramps_serial;
210 //rtexture_t *r_texture_fogintensity;
211
212 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
213 unsigned int r_numqueries;
214 unsigned int r_maxqueries;
215
216 typedef struct r_qwskincache_s
217 {
218         char name[MAX_QPATH];
219         skinframe_t *skinframe;
220 }
221 r_qwskincache_t;
222
223 static r_qwskincache_t *r_qwskincache;
224 static int r_qwskincache_size;
225
226 /// vertex coordinates for a quad that covers the screen exactly
227 const float r_screenvertex3f[12] =
228 {
229         0, 0, 0,
230         1, 0, 0,
231         1, 1, 0,
232         0, 1, 0
233 };
234
235 extern void R_DrawModelShadows(void);
236
237 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
238 {
239         int i;
240         for (i = 0;i < verts;i++)
241         {
242                 out[0] = in[0] * r;
243                 out[1] = in[1] * g;
244                 out[2] = in[2] * b;
245                 out[3] = in[3];
246                 in += 4;
247                 out += 4;
248         }
249 }
250
251 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
252 {
253         int i;
254         for (i = 0;i < verts;i++)
255         {
256                 out[0] = r;
257                 out[1] = g;
258                 out[2] = b;
259                 out[3] = a;
260                 out += 4;
261         }
262 }
263
264 // FIXME: move this to client?
265 void FOG_clear(void)
266 {
267         if (gamemode == GAME_NEHAHRA)
268         {
269                 Cvar_Set("gl_fogenable", "0");
270                 Cvar_Set("gl_fogdensity", "0.2");
271                 Cvar_Set("gl_fogred", "0.3");
272                 Cvar_Set("gl_foggreen", "0.3");
273                 Cvar_Set("gl_fogblue", "0.3");
274         }
275         r_refdef.fog_density = 0;
276         r_refdef.fog_red = 0;
277         r_refdef.fog_green = 0;
278         r_refdef.fog_blue = 0;
279         r_refdef.fog_alpha = 1;
280         r_refdef.fog_start = 0;
281         r_refdef.fog_end = 16384;
282         r_refdef.fog_height = 1<<30;
283         r_refdef.fog_fadedepth = 128;
284 }
285
286 static void R_BuildBlankTextures(void)
287 {
288         unsigned char data[4];
289         data[2] = 128; // normal X
290         data[1] = 128; // normal Y
291         data[0] = 255; // normal Z
292         data[3] = 128; // height
293         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
294         data[0] = 255;
295         data[1] = 255;
296         data[2] = 255;
297         data[3] = 255;
298         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
299         data[0] = 128;
300         data[1] = 128;
301         data[2] = 128;
302         data[3] = 255;
303         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
304         data[0] = 0;
305         data[1] = 0;
306         data[2] = 0;
307         data[3] = 255;
308         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
309 }
310
311 static void R_BuildNoTexture(void)
312 {
313         int x, y;
314         unsigned char pix[16][16][4];
315         // this makes a light grey/dark grey checkerboard texture
316         for (y = 0;y < 16;y++)
317         {
318                 for (x = 0;x < 16;x++)
319                 {
320                         if ((y < 8) ^ (x < 8))
321                         {
322                                 pix[y][x][0] = 128;
323                                 pix[y][x][1] = 128;
324                                 pix[y][x][2] = 128;
325                                 pix[y][x][3] = 255;
326                         }
327                         else
328                         {
329                                 pix[y][x][0] = 64;
330                                 pix[y][x][1] = 64;
331                                 pix[y][x][2] = 64;
332                                 pix[y][x][3] = 255;
333                         }
334                 }
335         }
336         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
337 }
338
339 static void R_BuildWhiteCube(void)
340 {
341         unsigned char data[6*1*1*4];
342         memset(data, 255, sizeof(data));
343         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
344 }
345
346 static void R_BuildNormalizationCube(void)
347 {
348         int x, y, side;
349         vec3_t v;
350         vec_t s, t, intensity;
351 #define NORMSIZE 64
352         unsigned char *data;
353         data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
354         for (side = 0;side < 6;side++)
355         {
356                 for (y = 0;y < NORMSIZE;y++)
357                 {
358                         for (x = 0;x < NORMSIZE;x++)
359                         {
360                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
361                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
362                                 switch(side)
363                                 {
364                                 default:
365                                 case 0:
366                                         v[0] = 1;
367                                         v[1] = -t;
368                                         v[2] = -s;
369                                         break;
370                                 case 1:
371                                         v[0] = -1;
372                                         v[1] = -t;
373                                         v[2] = s;
374                                         break;
375                                 case 2:
376                                         v[0] = s;
377                                         v[1] = 1;
378                                         v[2] = t;
379                                         break;
380                                 case 3:
381                                         v[0] = s;
382                                         v[1] = -1;
383                                         v[2] = -t;
384                                         break;
385                                 case 4:
386                                         v[0] = s;
387                                         v[1] = -t;
388                                         v[2] = 1;
389                                         break;
390                                 case 5:
391                                         v[0] = -s;
392                                         v[1] = -t;
393                                         v[2] = -1;
394                                         break;
395                                 }
396                                 intensity = 127.0f / sqrt(DotProduct(v, v));
397                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
398                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
399                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
400                                 data[((side*64+y)*64+x)*4+3] = 255;
401                         }
402                 }
403         }
404         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
405         Mem_Free(data);
406 }
407
408 static void R_BuildFogTexture(void)
409 {
410         int x, b;
411 #define FOGWIDTH 256
412         unsigned char data1[FOGWIDTH][4];
413         //unsigned char data2[FOGWIDTH][4];
414         double d, r, alpha;
415
416         r_refdef.fogmasktable_start = r_refdef.fog_start;
417         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
418         r_refdef.fogmasktable_range = r_refdef.fogrange;
419         r_refdef.fogmasktable_density = r_refdef.fog_density;
420
421         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
422         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
423         {
424                 d = (x * r - r_refdef.fogmasktable_start);
425                 if(developer_extra.integer)
426                         Con_DPrintf("%f ", d);
427                 d = max(0, d);
428                 if (r_fog_exp2.integer)
429                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
430                 else
431                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
432                 if(developer_extra.integer)
433                         Con_DPrintf(" : %f ", alpha);
434                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
435                 if(developer_extra.integer)
436                         Con_DPrintf(" = %f\n", alpha);
437                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
438         }
439
440         for (x = 0;x < FOGWIDTH;x++)
441         {
442                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
443                 data1[x][0] = b;
444                 data1[x][1] = b;
445                 data1[x][2] = b;
446                 data1[x][3] = 255;
447                 //data2[x][0] = 255 - b;
448                 //data2[x][1] = 255 - b;
449                 //data2[x][2] = 255 - b;
450                 //data2[x][3] = 255;
451         }
452         if (r_texture_fogattenuation)
453         {
454                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
455                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
456         }
457         else
458         {
459                 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);
460                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
461         }
462 }
463
464 //=======================================================================================================================================================
465
466 static const char *builtinshaderstring =
467 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
468 "// written by Forest 'LordHavoc' Hale\n"
469 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
470 "\n"
471 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
472 "# define USEFOG\n"
473 "#endif\n"
474 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
475 "#define USELIGHTMAP\n"
476 "#endif\n"
477 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING)\n"
478 "#define USEEYEVECTOR\n"
479 "#endif\n"
480 "\n"
481 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
482 "# extension GL_ARB_texture_rectangle : enable\n"
483 "#endif\n"
484 "\n"
485 "#ifdef USESHADOWMAP2D\n"
486 "# ifdef GL_EXT_gpu_shader4\n"
487 "#   extension GL_EXT_gpu_shader4 : enable\n"
488 "# endif\n"
489 "# ifdef GL_ARB_texture_gather\n"
490 "#   extension GL_ARB_texture_gather : enable\n"
491 "# else\n"
492 "#   ifdef GL_AMD_texture_texture4\n"
493 "#     extension GL_AMD_texture_texture4 : enable\n"
494 "#   endif\n"
495 "# endif\n"
496 "#endif\n"
497 "\n"
498 "#ifdef USESHADOWMAPCUBE\n"
499 "# extension GL_EXT_gpu_shader4 : enable\n"
500 "#endif\n"
501 "\n"
502 "//#ifdef USESHADOWSAMPLER\n"
503 "//# extension GL_ARB_shadow : enable\n"
504 "//#endif\n"
505 "\n"
506 "//#ifdef __GLSL_CG_DATA_TYPES\n"
507 "//# define myhalf half\n"
508 "//# define myhalf2 half2\n"
509 "//# define myhalf3 half3\n"
510 "//# define myhalf4 half4\n"
511 "//#else\n"
512 "# define myhalf float\n"
513 "# define myhalf2 vec2\n"
514 "# define myhalf3 vec3\n"
515 "# define myhalf4 vec4\n"
516 "//#endif\n"
517 "\n"
518 "#ifdef VERTEX_SHADER\n"
519 "uniform mat4 ModelViewProjectionMatrix;\n"
520 "#endif\n"
521 "\n"
522 "#ifdef MODE_DEPTH_OR_SHADOW\n"
523 "#ifdef VERTEX_SHADER\n"
524 "void main(void)\n"
525 "{\n"
526 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
527 "}\n"
528 "#endif\n"
529 "#else // !MODE_DEPTH_ORSHADOW\n"
530 "\n"
531 "\n"
532 "\n"
533 "\n"
534 "#ifdef MODE_SHOWDEPTH\n"
535 "#ifdef VERTEX_SHADER\n"
536 "void main(void)\n"
537 "{\n"
538 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
539 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
540 "}\n"
541 "#endif\n"
542 "\n"
543 "#ifdef FRAGMENT_SHADER\n"
544 "void main(void)\n"
545 "{\n"
546 "       gl_FragColor = gl_Color;\n"
547 "}\n"
548 "#endif\n"
549 "#else // !MODE_SHOWDEPTH\n"
550 "\n"
551 "\n"
552 "\n"
553 "\n"
554 "#ifdef MODE_POSTPROCESS\n"
555 "varying vec2 TexCoord1;\n"
556 "varying vec2 TexCoord2;\n"
557 "\n"
558 "#ifdef VERTEX_SHADER\n"
559 "void main(void)\n"
560 "{\n"
561 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
562 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
563 "#ifdef USEBLOOM\n"
564 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
565 "#endif\n"
566 "}\n"
567 "#endif\n"
568 "\n"
569 "#ifdef FRAGMENT_SHADER\n"
570 "uniform sampler2D Texture_First;\n"
571 "#ifdef USEBLOOM\n"
572 "uniform sampler2D Texture_Second;\n"
573 "#endif\n"
574 "#ifdef USEGAMMARAMPS\n"
575 "uniform sampler2D Texture_GammaRamps;\n"
576 "#endif\n"
577 "#ifdef USESATURATION\n"
578 "uniform float Saturation;\n"
579 "#endif\n"
580 "#ifdef USEVIEWTINT\n"
581 "uniform vec4 ViewTintColor;\n"
582 "#endif\n"
583 "//uncomment these if you want to use them:\n"
584 "uniform vec4 UserVec1;\n"
585 "// uniform vec4 UserVec2;\n"
586 "// uniform vec4 UserVec3;\n"
587 "// uniform vec4 UserVec4;\n"
588 "// uniform float ClientTime;\n"
589 "uniform vec2 PixelSize;\n"
590 "void main(void)\n"
591 "{\n"
592 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
593 "#ifdef USEBLOOM\n"
594 "       gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
595 "#endif\n"
596 "#ifdef USEVIEWTINT\n"
597 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
598 "#endif\n"
599 "\n"
600 "#ifdef USEPOSTPROCESSING\n"
601 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
602 "// 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"
603 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
604 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
605 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
606 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
607 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
608 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
609 "#endif\n"
610 "\n"
611 "#ifdef USESATURATION\n"
612 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
613 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
614 "       //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
615 "       gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
616 "#endif\n"
617 "\n"
618 "#ifdef USEGAMMARAMPS\n"
619 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
620 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
621 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
622 "#endif\n"
623 "}\n"
624 "#endif\n"
625 "#else // !MODE_POSTPROCESS\n"
626 "\n"
627 "\n"
628 "\n"
629 "\n"
630 "#ifdef MODE_GENERIC\n"
631 "#ifdef USEDIFFUSE\n"
632 "varying vec2 TexCoord1;\n"
633 "#endif\n"
634 "#ifdef USESPECULAR\n"
635 "varying vec2 TexCoord2;\n"
636 "#endif\n"
637 "#ifdef VERTEX_SHADER\n"
638 "void main(void)\n"
639 "{\n"
640 "       gl_FrontColor = gl_Color;\n"
641 "#ifdef USEDIFFUSE\n"
642 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
643 "#endif\n"
644 "#ifdef USESPECULAR\n"
645 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
646 "#endif\n"
647 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
648 "}\n"
649 "#endif\n"
650 "\n"
651 "#ifdef FRAGMENT_SHADER\n"
652 "#ifdef USEDIFFUSE\n"
653 "uniform sampler2D Texture_First;\n"
654 "#endif\n"
655 "#ifdef USESPECULAR\n"
656 "uniform sampler2D Texture_Second;\n"
657 "#endif\n"
658 "\n"
659 "void main(void)\n"
660 "{\n"
661 "       gl_FragColor = gl_Color;\n"
662 "#ifdef USEDIFFUSE\n"
663 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
664 "#endif\n"
665 "\n"
666 "#ifdef USESPECULAR\n"
667 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
668 "# ifdef USECOLORMAPPING\n"
669 "       gl_FragColor *= tex2;\n"
670 "# endif\n"
671 "# ifdef USEGLOW\n"
672 "       gl_FragColor += tex2;\n"
673 "# endif\n"
674 "# ifdef USEVERTEXTEXTUREBLEND\n"
675 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
676 "# endif\n"
677 "#endif\n"
678 "}\n"
679 "#endif\n"
680 "#else // !MODE_GENERIC\n"
681 "\n"
682 "\n"
683 "\n"
684 "\n"
685 "#ifdef MODE_BLOOMBLUR\n"
686 "varying TexCoord;\n"
687 "#ifdef VERTEX_SHADER\n"
688 "void main(void)\n"
689 "{\n"
690 "       gl_FrontColor = gl_Color;\n"
691 "       TexCoord = gl_MultiTexCoord0.xy;\n"
692 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
693 "}\n"
694 "#endif\n"
695 "\n"
696 "#ifdef FRAGMENT_SHADER\n"
697 "uniform sampler2D Texture_First;\n"
698 "uniform vec4 BloomBlur_Parameters;\n"
699 "\n"
700 "void main(void)\n"
701 "{\n"
702 "       int i;\n"
703 "       vec2 tc = TexCoord;\n"
704 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
705 "       tc += BloomBlur_Parameters.xy;\n"
706 "       for (i = 1;i < SAMPLES;i++)\n"
707 "       {\n"
708 "               color += texture2D(Texture_First, tc).rgb;\n"
709 "               tc += BloomBlur_Parameters.xy;\n"
710 "       }\n"
711 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
712 "}\n"
713 "#endif\n"
714 "#else // !MODE_BLOOMBLUR\n"
715 "#ifdef MODE_REFRACTION\n"
716 "varying vec2 TexCoord;\n"
717 "varying vec4 ModelViewProjectionPosition;\n"
718 "uniform mat4 TexMatrix;\n"
719 "#ifdef VERTEX_SHADER\n"
720 "\n"
721 "void main(void)\n"
722 "{\n"
723 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
724 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
725 "       ModelViewProjectionPosition = gl_Position;\n"
726 "}\n"
727 "#endif\n"
728 "\n"
729 "#ifdef FRAGMENT_SHADER\n"
730 "uniform sampler2D Texture_Normal;\n"
731 "uniform sampler2D Texture_Refraction;\n"
732 "uniform sampler2D Texture_Reflection;\n"
733 "\n"
734 "uniform vec4 DistortScaleRefractReflect;\n"
735 "uniform vec4 ScreenScaleRefractReflect;\n"
736 "uniform vec4 ScreenCenterRefractReflect;\n"
737 "uniform vec4 RefractColor;\n"
738 "uniform vec4 ReflectColor;\n"
739 "uniform float ReflectFactor;\n"
740 "uniform float ReflectOffset;\n"
741 "\n"
742 "void main(void)\n"
743 "{\n"
744 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
745 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
746 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
747 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
748 "       // FIXME temporary hack to detect the case that the reflection\n"
749 "       // gets blackened at edges due to leaving the area that contains actual\n"
750 "       // content.\n"
751 "       // Remove this 'ack once we have a better way to stop this thing from\n"
752 "       // 'appening.\n"
753 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
754 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
755 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
756 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
757 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
758 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
759 "}\n"
760 "#endif\n"
761 "#else // !MODE_REFRACTION\n"
762 "\n"
763 "\n"
764 "\n"
765 "\n"
766 "#ifdef MODE_WATER\n"
767 "varying vec2 TexCoord;\n"
768 "varying vec3 EyeVector;\n"
769 "varying vec4 ModelViewProjectionPosition;\n"
770 "#ifdef VERTEX_SHADER\n"
771 "uniform vec3 EyePosition;\n"
772 "uniform mat4 TexMatrix;\n"
773 "\n"
774 "void main(void)\n"
775 "{\n"
776 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
777 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
778 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
779 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
780 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
781 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
782 "       ModelViewProjectionPosition = gl_Position;\n"
783 "}\n"
784 "#endif\n"
785 "\n"
786 "#ifdef FRAGMENT_SHADER\n"
787 "uniform sampler2D Texture_Normal;\n"
788 "uniform sampler2D Texture_Refraction;\n"
789 "uniform sampler2D Texture_Reflection;\n"
790 "\n"
791 "uniform vec4 DistortScaleRefractReflect;\n"
792 "uniform vec4 ScreenScaleRefractReflect;\n"
793 "uniform vec4 ScreenCenterRefractReflect;\n"
794 "uniform vec4 RefractColor;\n"
795 "uniform vec4 ReflectColor;\n"
796 "uniform float ReflectFactor;\n"
797 "uniform float ReflectOffset;\n"
798 "\n"
799 "void main(void)\n"
800 "{\n"
801 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
802 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
803 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
804 "       vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
805 "       // FIXME temporary hack to detect the case that the reflection\n"
806 "       // gets blackened at edges due to leaving the area that contains actual\n"
807 "       // content.\n"
808 "       // Remove this 'ack once we have a better way to stop this thing from\n"
809 "       // 'appening.\n"
810 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
811 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
812 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
813 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
814 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
815 "       f       = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
816 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
817 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
818 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
819 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
820 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
821 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
822 "}\n"
823 "#endif\n"
824 "#else // !MODE_WATER\n"
825 "\n"
826 "\n"
827 "\n"
828 "\n"
829 "// common definitions between vertex shader and fragment shader:\n"
830 "\n"
831 "varying vec2 TexCoord;\n"
832 "#ifdef USEVERTEXTEXTUREBLEND\n"
833 "varying vec2 TexCoord2;\n"
834 "#endif\n"
835 "#ifdef USELIGHTMAP\n"
836 "varying vec2 TexCoordLightmap;\n"
837 "#endif\n"
838 "\n"
839 "#ifdef MODE_LIGHTSOURCE\n"
840 "varying vec3 CubeVector;\n"
841 "#endif\n"
842 "\n"
843 "#ifdef MODE_LIGHTSOURCE\n"
844 "varying vec3 LightVector;\n"
845 "#endif\n"
846 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
847 "varying vec3 LightVector;\n"
848 "#endif\n"
849 "\n"
850 "#ifdef USEEYEVECTOR\n"
851 "varying vec3 EyeVector;\n"
852 "#endif\n"
853 "#ifdef USEFOG\n"
854 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
855 "#endif\n"
856 "\n"
857 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
858 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
859 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
860 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
861 "#endif\n"
862 "\n"
863 "#ifdef USEREFLECTION\n"
864 "varying vec4 ModelViewProjectionPosition;\n"
865 "#endif\n"
866 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
867 "uniform vec3 LightPosition;\n"
868 "varying vec4 ModelViewPosition;\n"
869 "#endif\n"
870 "\n"
871 "#ifdef MODE_LIGHTSOURCE\n"
872 "uniform vec3 LightPosition;\n"
873 "#endif\n"
874 "uniform vec3 EyePosition;\n"
875 "#ifdef MODE_LIGHTDIRECTION\n"
876 "uniform vec3 LightDir;\n"
877 "#endif\n"
878 "uniform vec4 FogPlane;\n"
879 "\n"
880 "\n"
881 "\n"
882 "\n"
883 "\n"
884 "// 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"
885 "\n"
886 "// fragment shader specific:\n"
887 "#ifdef FRAGMENT_SHADER\n"
888 "\n"
889 "uniform sampler2D Texture_Normal;\n"
890 "uniform sampler2D Texture_Color;\n"
891 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
892 "uniform sampler2D Texture_Gloss;\n"
893 "//#endif\n"
894 "#ifdef USEGLOW\n"
895 "uniform sampler2D Texture_Glow;\n"
896 "#endif\n"
897 "#ifdef USEVERTEXTEXTUREBLEND\n"
898 "uniform sampler2D Texture_SecondaryNormal;\n"
899 "uniform sampler2D Texture_SecondaryColor;\n"
900 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
901 "uniform sampler2D Texture_SecondaryGloss;\n"
902 "//#endif\n"
903 "#ifdef USEGLOW\n"
904 "uniform sampler2D Texture_SecondaryGlow;\n"
905 "#endif\n"
906 "#endif\n"
907 "#ifdef USECOLORMAPPING\n"
908 "uniform sampler2D Texture_Pants;\n"
909 "uniform sampler2D Texture_Shirt;\n"
910 "#endif\n"
911 "#ifdef USEFOG\n"
912 "uniform sampler2D Texture_FogMask;\n"
913 "#endif\n"
914 "#ifdef USELIGHTMAP\n"
915 "uniform sampler2D Texture_Lightmap;\n"
916 "#endif\n"
917 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
918 "uniform sampler2D Texture_Deluxemap;\n"
919 "#endif\n"
920 "#ifdef USEREFLECTION\n"
921 "uniform sampler2D Texture_Reflection;\n"
922 "#endif\n"
923 "\n"
924 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
925 "uniform sampler2DRect Texture_ScreenDepth;\n"
926 "uniform sampler2DRect Texture_ScreenNormalMap;\n"
927 "#endif\n"
928 "#ifdef USEDEFERREDLIGHTMAP\n"
929 "uniform sampler2DRect Texture_ScreenDiffuse;\n"
930 "uniform sampler2DRect Texture_ScreenSpecular;\n"
931 "#endif\n"
932 "\n"
933 "uniform myhalf3 Color_Pants;\n"
934 "uniform myhalf3 Color_Shirt;\n"
935 "uniform myhalf3 FogColor;\n"
936 "\n"
937 "#ifdef USEFOG\n"
938 "uniform float FogRangeRecip;\n"
939 "uniform float FogPlaneViewDist;\n"
940 "uniform float FogHeightFade;\n"
941 "float FogVertex(void)\n"
942 "{\n"
943 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
944 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
945 "       float fogfrac;\n"
946 "#ifdef USEFOGOUTSIDE\n"
947 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
948 "#else\n"
949 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
950 "#endif\n"
951 "       return float(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
952 "}\n"
953 "#endif\n"
954 "\n"
955 "#ifdef USEOFFSETMAPPING\n"
956 "uniform float OffsetMapping_Scale;\n"
957 "vec2 OffsetMapping(vec2 TexCoord)\n"
958 "{\n"
959 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
960 "       // 14 sample relief mapping: linear search and then binary search\n"
961 "       // this basically steps forward a small amount repeatedly until it finds\n"
962 "       // itself inside solid, then jitters forward and back using decreasing\n"
963 "       // amounts to find the impact\n"
964 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
965 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
966 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
967 "       vec3 RT = vec3(TexCoord, 1);\n"
968 "       OffsetVector *= 0.1;\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);\n"
974 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
975 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
976 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
977 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
978 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
979 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
980 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
981 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
982 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
983 "       return RT.xy;\n"
984 "#else\n"
985 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
986 "       // this basically moves forward the full distance, and then backs up based\n"
987 "       // on height of samples\n"
988 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
989 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
990 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
991 "       TexCoord += OffsetVector;\n"
992 "       OffsetVector *= 0.333;\n"
993 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
994 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
995 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
996 "       return TexCoord;\n"
997 "#endif\n"
998 "}\n"
999 "#endif // USEOFFSETMAPPING\n"
1000 "\n"
1001 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1002 "uniform sampler2D Texture_Attenuation;\n"
1003 "uniform samplerCube Texture_Cube;\n"
1004 "\n"
1005 "#ifdef USESHADOWMAPRECT\n"
1006 "# ifdef USESHADOWSAMPLER\n"
1007 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1008 "# else\n"
1009 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1010 "# endif\n"
1011 "#endif\n"
1012 "\n"
1013 "#ifdef USESHADOWMAP2D\n"
1014 "# ifdef USESHADOWSAMPLER\n"
1015 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1016 "# else\n"
1017 "uniform sampler2D Texture_ShadowMap2D;\n"
1018 "# endif\n"
1019 "#endif\n"
1020 "\n"
1021 "#ifdef USESHADOWMAPVSDCT\n"
1022 "uniform samplerCube Texture_CubeProjection;\n"
1023 "#endif\n"
1024 "\n"
1025 "#ifdef USESHADOWMAPCUBE\n"
1026 "# ifdef USESHADOWSAMPLER\n"
1027 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1028 "# else\n"
1029 "uniform samplerCube Texture_ShadowMapCube;\n"
1030 "# endif\n"
1031 "#endif\n"
1032 "\n"
1033 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1034 "uniform vec2 ShadowMap_TextureScale;\n"
1035 "uniform vec4 ShadowMap_Parameters;\n"
1036 "#endif\n"
1037 "\n"
1038 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1039 "# ifndef USESHADOWMAPVSDCT\n"
1040 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1041 "{\n"
1042 "       vec3 adir = abs(dir);\n"
1043 "       vec2 tc;\n"
1044 "       vec2 offset;\n"
1045 "       float ma;\n"
1046 "       if (adir.x > adir.y)\n"
1047 "       {\n"
1048 "               if (adir.x > adir.z) // X\n"
1049 "               {\n"
1050 "                       ma = adir.x;\n"
1051 "                       tc = dir.zy;\n"
1052 "                       offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
1053 "               }\n"
1054 "               else // Z\n"
1055 "               {\n"
1056 "                       ma = adir.z;\n"
1057 "                       tc = dir.xy;\n"
1058 "                       offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1059 "               }\n"
1060 "       }\n"
1061 "       else\n"
1062 "       {\n"
1063 "               if (adir.y > adir.z) // Y\n"
1064 "               {\n"
1065 "                       ma = adir.y;\n"
1066 "                       tc = dir.xz;\n"
1067 "                       offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
1068 "               }\n"
1069 "               else // Z\n"
1070 "               {\n"
1071 "                       ma = adir.z;\n"
1072 "                       tc = dir.xy;\n"
1073 "                       offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1074 "               }\n"
1075 "       }\n"
1076 "\n"
1077 "       vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1078 "       stc.xy += offset * ShadowMap_Parameters.y;\n"
1079 "       stc.z += ShadowMap_Parameters.z;\n"
1080 "       return stc;\n"
1081 "}\n"
1082 "# else\n"
1083 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1084 "{\n"
1085 "       vec3 adir = abs(dir);\n"
1086 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1087 "       float ma = max(max(adir.x, adir.y), adir.z);\n"
1088 "       vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1089 "       stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
1090 "       stc.z += ShadowMap_Parameters.z;\n"
1091 "       return stc;\n"
1092 "}\n"
1093 "# endif\n"
1094 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1095 "\n"
1096 "#ifdef USESHADOWMAPCUBE\n"
1097 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1098 "{\n"
1099 "       vec3 adir = abs(dir);\n"
1100 "       return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1101 "}\n"
1102 "#endif\n"
1103 "\n"
1104 "# ifdef USESHADOWMAPRECT\n"
1105 "float ShadowMapCompare(vec3 dir)\n"
1106 "{\n"
1107 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1108 "       float f;\n"
1109 "#  ifdef USESHADOWSAMPLER\n"
1110 "\n"
1111 "#    ifdef USESHADOWMAPPCF\n"
1112 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1113 "       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"
1114 "#    else\n"
1115 "       f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1116 "#    endif\n"
1117 "\n"
1118 "#  else\n"
1119 "\n"
1120 "#    ifdef USESHADOWMAPPCF\n"
1121 "#      if USESHADOWMAPPCF > 1\n"
1122 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1123 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1124 "       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"
1125 "       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"
1126 "       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"
1127 "       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"
1128 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1129 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1130 "#      else\n"
1131 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1132 "       vec2 offset = fract(shadowmaptc.xy);\n"
1133 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1134 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1135 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1136 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1137 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1138 "#      endif\n"
1139 "#    else\n"
1140 "       f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1141 "#    endif\n"
1142 "\n"
1143 "#  endif\n"
1144 "       return f;\n"
1145 "}\n"
1146 "# endif\n"
1147 "\n"
1148 "# ifdef USESHADOWMAP2D\n"
1149 "float ShadowMapCompare(vec3 dir)\n"
1150 "{\n"
1151 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1152 "       float f;\n"
1153 "\n"
1154 "#  ifdef USESHADOWSAMPLER\n"
1155 "#    ifdef USESHADOWMAPPCF\n"
1156 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1157 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1158 "       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"
1159 "#    else\n"
1160 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1161 "#    endif\n"
1162 "#  else\n"
1163 "#    ifdef USESHADOWMAPPCF\n"
1164 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1165 "#      ifdef GL_ARB_texture_gather\n"
1166 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1167 "#      else\n"
1168 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1169 "#      endif\n"
1170 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1171 "       center *= ShadowMap_TextureScale;\n"
1172 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1173 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1174 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1175 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1176 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1177 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1178 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1179 "#     else\n"
1180 "#      ifdef GL_EXT_gpu_shader4\n"
1181 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1182 "#      else\n"
1183 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1184 "#      endif\n"
1185 "#      if USESHADOWMAPPCF > 1\n"
1186 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1187 "       center *= ShadowMap_TextureScale;\n"
1188 "       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"
1189 "       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"
1190 "       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"
1191 "       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"
1192 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1193 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1194 "#      else\n"
1195 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1196 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1197 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1198 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1199 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1200 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1201 "#      endif\n"
1202 "#     endif\n"
1203 "#    else\n"
1204 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1205 "#    endif\n"
1206 "#  endif\n"
1207 "       return f;\n"
1208 "}\n"
1209 "# endif\n"
1210 "\n"
1211 "# ifdef USESHADOWMAPCUBE\n"
1212 "float ShadowMapCompare(vec3 dir)\n"
1213 "{\n"
1214 "       // apply depth texture cubemap as light filter\n"
1215 "       vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1216 "       float f;\n"
1217 "#  ifdef USESHADOWSAMPLER\n"
1218 "       f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1219 "#  else\n"
1220 "       f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1221 "#  endif\n"
1222 "       return f;\n"
1223 "}\n"
1224 "# endif\n"
1225 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
1226 "#endif // FRAGMENT_SHADER\n"
1227 "\n"
1228 "\n"
1229 "\n"
1230 "\n"
1231 "#ifdef MODE_DEFERREDGEOMETRY\n"
1232 "#ifdef VERTEX_SHADER\n"
1233 "uniform mat4 TexMatrix;\n"
1234 "#ifdef USEVERTEXTEXTUREBLEND\n"
1235 "uniform mat4 BackgroundTexMatrix;\n"
1236 "#endif\n"
1237 "uniform mat4 ModelViewMatrix;\n"
1238 "void main(void)\n"
1239 "{\n"
1240 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1241 "#ifdef USEVERTEXTEXTUREBLEND\n"
1242 "       gl_FrontColor = gl_Color;\n"
1243 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1244 "#endif\n"
1245 "\n"
1246 "       // transform unnormalized eye direction into tangent space\n"
1247 "#ifdef USEOFFSETMAPPING\n"
1248 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1249 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1250 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1251 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1252 "#endif\n"
1253 "\n"
1254 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1255 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1256 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1257 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1258 "}\n"
1259 "#endif // VERTEX_SHADER\n"
1260 "\n"
1261 "#ifdef FRAGMENT_SHADER\n"
1262 "void main(void)\n"
1263 "{\n"
1264 "#ifdef USEOFFSETMAPPING\n"
1265 "       // apply offsetmapping\n"
1266 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1267 "#define TexCoord TexCoordOffset\n"
1268 "#endif\n"
1269 "\n"
1270 "#ifdef USEALPHAKILL\n"
1271 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1272 "               discard;\n"
1273 "#endif\n"
1274 "\n"
1275 "#ifdef USEVERTEXTEXTUREBLEND\n"
1276 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1277 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1278 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1279 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1280 "#endif\n"
1281 "\n"
1282 "#ifdef USEVERTEXTEXTUREBLEND\n"
1283 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1284 "#else\n"
1285 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1286 "#endif\n"
1287 "\n"
1288 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), 1);\n"
1289 "}\n"
1290 "#endif // FRAGMENT_SHADER\n"
1291 "#else // !MODE_DEFERREDGEOMETRY\n"
1292 "\n"
1293 "\n"
1294 "\n"
1295 "\n"
1296 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1297 "#ifdef VERTEX_SHADER\n"
1298 "uniform mat4 ModelViewMatrix;\n"
1299 "void main(void)\n"
1300 "{\n"
1301 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1302 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1303 "}\n"
1304 "#endif // VERTEX_SHADER\n"
1305 "\n"
1306 "#ifdef FRAGMENT_SHADER\n"
1307 "uniform mat4 ViewToLight;\n"
1308 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1309 "uniform vec2 ScreenToDepth;\n"
1310 "uniform myhalf3 DeferredColor_Ambient;\n"
1311 "uniform myhalf3 DeferredColor_Diffuse;\n"
1312 "#ifdef USESPECULAR\n"
1313 "uniform myhalf3 DeferredColor_Specular;\n"
1314 "uniform myhalf SpecularPower;\n"
1315 "#endif\n"
1316 "void main(void)\n"
1317 "{\n"
1318 "       // calculate viewspace pixel position\n"
1319 "       vec3 position;\n"
1320 "       position.z = ScreenToDepth.y / (texture2DRect(Texture_ScreenDepth, gl_FragCoord.xy).r + ScreenToDepth.x);\n"
1321 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1322 "       // decode viewspace pixel normal\n"
1323 "       myhalf4 normalmap = texture2DRect(Texture_ScreenNormalMap, gl_FragCoord.xy);\n"
1324 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1325 "       // surfacenormal = pixel normal in viewspace\n"
1326 "       // LightVector = pixel to light in viewspace\n"
1327 "       // CubeVector = position in lightspace\n"
1328 "       // eyevector = pixel to view in viewspace\n"
1329 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1330 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1331 "#ifdef USEDIFFUSE\n"
1332 "       // calculate diffuse shading\n"
1333 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1334 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1335 "#endif\n"
1336 "#ifdef USESPECULAR\n"
1337 "       // calculate directional shading\n"
1338 "       vec3 eyevector = position * -1.0;\n"
1339 "#  ifdef USEEXACTSPECULARMATH\n"
1340 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
1341 "#  else\n"
1342 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1343 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1344 "#  endif\n"
1345 "#endif\n"
1346 "\n"
1347 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1348 "       fade *= ShadowMapCompare(CubeVector);\n"
1349 "#endif\n"
1350 "\n"
1351 "#ifdef USEDIFFUSE\n"
1352 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1353 "#else\n"
1354 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1355 "#endif\n"
1356 "#ifdef USESPECULAR\n"
1357 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1358 "#else\n"
1359 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1360 "#endif\n"
1361 "\n"
1362 "# ifdef USECUBEFILTER\n"
1363 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1364 "       gl_FragData[0].rgb *= cubecolor;\n"
1365 "       gl_FragData[1].rgb *= cubecolor;\n"
1366 "# endif\n"
1367 "}\n"
1368 "#endif // FRAGMENT_SHADER\n"
1369 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1370 "\n"
1371 "\n"
1372 "\n"
1373 "\n"
1374 "#ifdef VERTEX_SHADER\n"
1375 "uniform mat4 TexMatrix;\n"
1376 "#ifdef USEVERTEXTEXTUREBLEND\n"
1377 "uniform mat4 BackgroundTexMatrix;\n"
1378 "#endif\n"
1379 "#ifdef MODE_LIGHTSOURCE\n"
1380 "uniform mat4 ModelToLight;\n"
1381 "#endif\n"
1382 "void main(void)\n"
1383 "{\n"
1384 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1385 "       gl_FrontColor = gl_Color;\n"
1386 "#endif\n"
1387 "       // copy the surface texcoord\n"
1388 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1389 "#ifdef USEVERTEXTEXTUREBLEND\n"
1390 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1391 "#endif\n"
1392 "#ifdef USELIGHTMAP\n"
1393 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1394 "#endif\n"
1395 "\n"
1396 "#ifdef MODE_LIGHTSOURCE\n"
1397 "       // transform vertex position into light attenuation/cubemap space\n"
1398 "       // (-1 to +1 across the light box)\n"
1399 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1400 "\n"
1401 "# ifdef USEDIFFUSE\n"
1402 "       // transform unnormalized light direction into tangent space\n"
1403 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1404 "       //  normalize it per pixel)\n"
1405 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1406 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1407 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1408 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1409 "# endif\n"
1410 "#endif\n"
1411 "\n"
1412 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1413 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1414 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1415 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1416 "#endif\n"
1417 "\n"
1418 "       // transform unnormalized eye direction into tangent space\n"
1419 "#ifdef USEEYEVECTOR\n"
1420 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1421 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1422 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1423 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1424 "#endif\n"
1425 "\n"
1426 "#ifdef USEFOG\n"
1427 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1428 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1429 "#endif\n"
1430 "\n"
1431 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1432 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1433 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1434 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1435 "#endif\n"
1436 "\n"
1437 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1438 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1439 "\n"
1440 "#ifdef USEREFLECTION\n"
1441 "       ModelViewProjectionPosition = gl_Position;\n"
1442 "#endif\n"
1443 "}\n"
1444 "#endif // VERTEX_SHADER\n"
1445 "\n"
1446 "\n"
1447 "\n"
1448 "\n"
1449 "#ifdef FRAGMENT_SHADER\n"
1450 "#ifdef USEDEFERREDLIGHTMAP\n"
1451 "uniform myhalf3 DeferredMod_Diffuse;\n"
1452 "uniform myhalf3 DeferredMod_Specular;\n"
1453 "#endif\n"
1454 "uniform myhalf3 Color_Ambient;\n"
1455 "uniform myhalf3 Color_Diffuse;\n"
1456 "uniform myhalf3 Color_Specular;\n"
1457 "uniform myhalf SpecularPower;\n"
1458 "#ifdef USEGLOW\n"
1459 "uniform myhalf3 Color_Glow;\n"
1460 "#endif\n"
1461 "uniform myhalf Alpha;\n"
1462 "#ifdef USEREFLECTION\n"
1463 "uniform vec4 DistortScaleRefractReflect;\n"
1464 "uniform vec4 ScreenScaleRefractReflect;\n"
1465 "uniform vec4 ScreenCenterRefractReflect;\n"
1466 "uniform myhalf4 ReflectColor;\n"
1467 "#endif\n"
1468 "#ifdef MODE_LIGHTDIRECTION\n"
1469 "uniform myhalf3 LightColor;\n"
1470 "#endif\n"
1471 "#ifdef MODE_LIGHTSOURCE\n"
1472 "uniform myhalf3 LightColor;\n"
1473 "#endif\n"
1474 "void main(void)\n"
1475 "{\n"
1476 "#ifdef USEOFFSETMAPPING\n"
1477 "       // apply offsetmapping\n"
1478 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1479 "#define TexCoord TexCoordOffset\n"
1480 "#endif\n"
1481 "\n"
1482 "       // combine the diffuse textures (base, pants, shirt)\n"
1483 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1484 "#ifdef USEALPHAKILL\n"
1485 "       if (color.a < 0.5)\n"
1486 "               discard;\n"
1487 "#endif\n"
1488 "       color.a *= Alpha;\n"
1489 "#ifdef USECOLORMAPPING\n"
1490 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1491 "#endif\n"
1492 "#ifdef USEVERTEXTEXTUREBLEND\n"
1493 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1494 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1495 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1496 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1497 "       color.a = 1.0;\n"
1498 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1499 "#endif\n"
1500 "\n"
1501 "       // get the surface normal\n"
1502 "#ifdef USEVERTEXTEXTUREBLEND\n"
1503 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1504 "#else\n"
1505 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1506 "#endif\n"
1507 "\n"
1508 "       // get the material colors\n"
1509 "       myhalf3 diffusetex = color.rgb;\n"
1510 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1511 "# ifdef USEVERTEXTEXTUREBLEND\n"
1512 "       myhalf3 glosstex = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1513 "# else\n"
1514 "       myhalf3 glosstex = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1515 "# endif\n"
1516 "#endif\n"
1517 "\n"
1518 "\n"
1519 "\n"
1520 "\n"
1521 "#ifdef MODE_LIGHTSOURCE\n"
1522 "       // light source\n"
1523 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1524 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1525 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1526 "#ifdef USESPECULAR\n"
1527 "#ifdef USEEXACTSPECULARMATH\n"
1528 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1529 "#else\n"
1530 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1531 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1532 "#endif\n"
1533 "       color.rgb += glosstex * (specular * Color_Specular);\n"
1534 "#endif\n"
1535 "       color.rgb *= LightColor;\n"
1536 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1537 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1538 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1539 "#endif\n"
1540 "# ifdef USECUBEFILTER\n"
1541 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1542 "# endif\n"
1543 "#endif // MODE_LIGHTSOURCE\n"
1544 "\n"
1545 "\n"
1546 "\n"
1547 "\n"
1548 "#ifdef MODE_LIGHTDIRECTION\n"
1549 "#define SHADING\n"
1550 "#ifdef USEDIFFUSE\n"
1551 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1552 "#endif\n"
1553 "#define lightcolor LightColor\n"
1554 "#endif // MODE_LIGHTDIRECTION\n"
1555 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1556 "#define SHADING\n"
1557 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1558 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1559 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1560 "       // convert modelspace light vector to tangentspace\n"
1561 "       myhalf3 lightnormal;\n"
1562 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1563 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1564 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1565 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1566 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1567 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1568 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1569 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1570 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1571 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1572 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1573 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1574 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1575 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1576 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1577 "#define SHADING\n"
1578 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1579 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1580 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1581 "#endif\n"
1582 "\n"
1583 "\n"
1584 "\n"
1585 "\n"
1586 "#ifdef MODE_LIGHTMAP\n"
1587 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1588 "#endif // MODE_LIGHTMAP\n"
1589 "#ifdef MODE_VERTEXCOLOR\n"
1590 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1591 "#endif // MODE_VERTEXCOLOR\n"
1592 "#ifdef MODE_FLATCOLOR\n"
1593 "       color.rgb = diffusetex * Color_Ambient;\n"
1594 "#endif // MODE_FLATCOLOR\n"
1595 "\n"
1596 "\n"
1597 "\n"
1598 "\n"
1599 "#ifdef SHADING\n"
1600 "# ifdef USEDIFFUSE\n"
1601 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1602 "#  ifdef USESPECULAR\n"
1603 "#   ifdef USEEXACTSPECULARMATH\n"
1604 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1605 "#   else\n"
1606 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1607 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1608 "#   endif\n"
1609 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
1610 "#  else\n"
1611 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1612 "#  endif\n"
1613 "# else\n"
1614 "       color.rgb = diffusetex * Color_Ambient;\n"
1615 "# endif\n"
1616 "#endif\n"
1617 "\n"
1618 "#ifdef USEDEFERREDLIGHTMAP\n"
1619 "       color.rgb += diffusetex * myhalf3(texture2DRect(Texture_ScreenDiffuse, gl_FragCoord.xy)) * DeferredMod_Diffuse;\n"
1620 "       color.rgb += glosstex * myhalf3(texture2DRect(Texture_ScreenSpecular, gl_FragCoord.xy)) * DeferredMod_Specular;\n"
1621 "#endif\n"
1622 "\n"
1623 "#ifdef USEGLOW\n"
1624 "#ifdef USEVERTEXTEXTUREBLEND\n"
1625 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1626 "#else\n"
1627 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1628 "#endif\n"
1629 "#endif\n"
1630 "\n"
1631 "#ifdef USEFOG\n"
1632 "#ifdef MODE_LIGHTSOURCE\n"
1633 "       color.rgb *= myhalf(FogVertex());\n"
1634 "#else\n"
1635 "       color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1636 "#endif\n"
1637 "#endif\n"
1638 "\n"
1639 "       // 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"
1640 "#ifdef USEREFLECTION\n"
1641 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1642 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1643 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1644 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1645 "       // FIXME temporary hack to detect the case that the reflection\n"
1646 "       // gets blackened at edges due to leaving the area that contains actual\n"
1647 "       // content.\n"
1648 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1649 "       // 'appening.\n"
1650 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1651 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1652 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1653 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1654 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1655 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1656 "#endif\n"
1657 "\n"
1658 "       gl_FragColor = vec4(color);\n"
1659 "}\n"
1660 "#endif // FRAGMENT_SHADER\n"
1661 "\n"
1662 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1663 "#endif // !MODE_DEFERREDGEOMETRY\n"
1664 "#endif // !MODE_WATER\n"
1665 "#endif // !MODE_REFRACTION\n"
1666 "#endif // !MODE_BLOOMBLUR\n"
1667 "#endif // !MODE_GENERIC\n"
1668 "#endif // !MODE_POSTPROCESS\n"
1669 "#endif // !MODE_SHOWDEPTH\n"
1670 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1671 ;
1672
1673 /*
1674 =========================================================================================================================================================
1675
1676
1677
1678 =========================================================================================================================================================
1679
1680
1681
1682 =========================================================================================================================================================
1683
1684
1685
1686 =========================================================================================================================================================
1687
1688
1689
1690 =========================================================================================================================================================
1691
1692
1693
1694 =========================================================================================================================================================
1695
1696
1697
1698 =========================================================================================================================================================
1699 */
1700
1701 const char *builtincgshaderstring =
1702 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1703 "// written by Forest 'LordHavoc' Hale\n"
1704 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1705 "\n"
1706 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
1707 "# define USEFOG\n"
1708 "#endif\n"
1709 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1710 "#define USELIGHTMAP\n"
1711 "#endif\n"
1712 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING)\n"
1713 "#define USEEYEVECTOR\n"
1714 "#endif\n"
1715 "\n"
1716 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1717 "#ifdef VERTEX_SHADER\n"
1718 "void main\n"
1719 "(\n"
1720 "float4 gl_Vertex : POSITION,\n"
1721 "uniform float4x4 ModelViewProjectionMatrix,\n"
1722 "out float4 gl_Position : POSITION\n"
1723 ")\n"
1724 "{\n"
1725 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1726 "}\n"
1727 "#endif\n"
1728 "#else // !MODE_DEPTH_ORSHADOW\n"
1729 "\n"
1730 "\n"
1731 "\n"
1732 "\n"
1733 "#ifdef MODE_SHOWDEPTH\n"
1734 "#ifdef VERTEX_SHADER\n"
1735 "void main\n"
1736 "(\n"
1737 "float4 gl_Vertex : POSITION,\n"
1738 "uniform float4x4 ModelViewProjectionMatrix,\n"
1739 "out float4 gl_Position : POSITION,\n"
1740 "out float4 gl_FrontColor : COLOR0\n"
1741 ")\n"
1742 "{\n"
1743 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1744 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1745 "}\n"
1746 "#endif\n"
1747 "\n"
1748 "#ifdef FRAGMENT_SHADER\n"
1749 "void main\n"
1750 "(\n"
1751 "float4 gl_FrontColor : COLOR0,\n"
1752 "out float4 gl_FragColor : COLOR\n"
1753 ")\n"
1754 "{\n"
1755 "       gl_FragColor = gl_FrontColor;\n"
1756 "}\n"
1757 "#endif\n"
1758 "#else // !MODE_SHOWDEPTH\n"
1759 "\n"
1760 "\n"
1761 "\n"
1762 "\n"
1763 "#ifdef MODE_POSTPROCESS\n"
1764 "\n"
1765 "#ifdef VERTEX_SHADER\n"
1766 "void main\n"
1767 "(\n"
1768 "float4 gl_Vertex : POSITION,\n"
1769 "uniform float4x4 ModelViewProjectionMatrix,\n"
1770 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1771 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1772 "out float4 gl_Position : POSITION,\n"
1773 "out float2 TexCoord1 : TEXCOORD0,\n"
1774 "out float2 TexCoord2 : TEXCOORD1\n"
1775 ")\n"
1776 "{\n"
1777 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1778 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1779 "#ifdef USEBLOOM\n"
1780 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1781 "#endif\n"
1782 "}\n"
1783 "#endif\n"
1784 "\n"
1785 "#ifdef FRAGMENT_SHADER\n"
1786 "void main\n"
1787 "(\n"
1788 "float2 TexCoord1 : TEXCOORD0,\n"
1789 "float2 TexCoord2 : TEXCOORD1,\n"
1790 "uniform sampler2D Texture_First,\n"
1791 "#ifdef USEBLOOM\n"
1792 "uniform sampler2D Texture_Second,\n"
1793 "#endif\n"
1794 "#ifdef USEGAMMARAMPS\n"
1795 "uniform sampler2D Texture_GammaRamps,\n"
1796 "#endif\n"
1797 "#ifdef USESATURATION\n"
1798 "uniform float Saturation,\n"
1799 "#endif\n"
1800 "#ifdef USEVIEWTINT\n"
1801 "uniform float4 ViewTintColor,\n"
1802 "#endif\n"
1803 "uniform float4 UserVec1,\n"
1804 "uniform float4 UserVec2,\n"
1805 "uniform float4 UserVec3,\n"
1806 "uniform float4 UserVec4,\n"
1807 "uniform float ClientTime,\n"
1808 "uniform float2 PixelSize,\n"
1809 "out float4 gl_FragColor : COLOR\n"
1810 ")\n"
1811 "{\n"
1812 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1813 "#ifdef USEBLOOM\n"
1814 "       gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
1815 "#endif\n"
1816 "#ifdef USEVIEWTINT\n"
1817 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1818 "#endif\n"
1819 "\n"
1820 "#ifdef USEPOSTPROCESSING\n"
1821 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1822 "// 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"
1823 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1824 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1825 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1826 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
1827 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
1828 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
1829 "#endif\n"
1830 "\n"
1831 "#ifdef USESATURATION\n"
1832 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
1833 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
1834 "       //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
1835 "       gl_FragColor.rgb = mix(float3(y), gl_FragColor.rgb, Saturation);\n"
1836 "#endif\n"
1837 "\n"
1838 "#ifdef USEGAMMARAMPS\n"
1839 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
1840 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
1841 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
1842 "#endif\n"
1843 "}\n"
1844 "#endif\n"
1845 "#else // !MODE_POSTPROCESS\n"
1846 "\n"
1847 "\n"
1848 "\n"
1849 "\n"
1850 "#ifdef MODE_GENERIC\n"
1851 "#ifdef VERTEX_SHADER\n"
1852 "void main\n"
1853 "(\n"
1854 "float4 gl_Vertex : POSITION,\n"
1855 "uniform float4x4 ModelViewProjectionMatrix,\n"
1856 "float4 gl_Color : COLOR0,\n"
1857 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1858 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1859 "out float4 gl_Position : POSITION,\n"
1860 "out float4 gl_FrontColor : COLOR,\n"
1861 "out float2 TexCoord1 : TEXCOORD0,\n"
1862 "out float2 TexCoord2 : TEXCOORD1\n"
1863 ")\n"
1864 "{\n"
1865 "       gl_FrontColor = gl_Color;\n"
1866 "#ifdef USEDIFFUSE\n"
1867 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1868 "#endif\n"
1869 "#ifdef USESPECULAR\n"
1870 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1871 "#endif\n"
1872 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1873 "}\n"
1874 "#endif\n"
1875 "\n"
1876 "#ifdef FRAGMENT_SHADER\n"
1877 "\n"
1878 "void main\n"
1879 "(\n"
1880 "float4 gl_FrontColor : COLOR,\n"
1881 "float2 TexCoord1 : TEXCOORD0,\n"
1882 "float2 TexCoord2 : TEXCOORD1,\n"
1883 "#ifdef USEDIFFUSE\n"
1884 "uniform sampler2D Texture_First,\n"
1885 "#endif\n"
1886 "#ifdef USESPECULAR\n"
1887 "uniform sampler2D Texture_Second,\n"
1888 "#endif\n"
1889 "out float4 gl_FragColor : COLOR\n"
1890 ")\n"
1891 "{\n"
1892 "       gl_FragColor = gl_FrontColor;\n"
1893 "#ifdef USEDIFFUSE\n"
1894 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
1895 "#endif\n"
1896 "\n"
1897 "#ifdef USESPECULAR\n"
1898 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
1899 "# ifdef USECOLORMAPPING\n"
1900 "       gl_FragColor *= tex2;\n"
1901 "# endif\n"
1902 "# ifdef USEGLOW\n"
1903 "       gl_FragColor += tex2;\n"
1904 "# endif\n"
1905 "# ifdef USEVERTEXTEXTUREBLEND\n"
1906 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
1907 "# endif\n"
1908 "#endif\n"
1909 "}\n"
1910 "#endif\n"
1911 "#else // !MODE_GENERIC\n"
1912 "\n"
1913 "\n"
1914 "\n"
1915 "\n"
1916 "#ifdef MODE_BLOOMBLUR\n"
1917 "#ifdef VERTEX_SHADER\n"
1918 "void main\n"
1919 "(\n"
1920 "float4 gl_Vertex : POSITION,\n"
1921 "uniform float4x4 ModelViewProjectionMatrix,\n"
1922 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1923 "out float4 gl_Position : POSITION,\n"
1924 "out float2 TexCoord : TEXCOORD0\n"
1925 ")\n"
1926 "{\n"
1927 "       TexCoord = gl_MultiTexCoord0.xy;\n"
1928 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1929 "}\n"
1930 "#endif\n"
1931 "\n"
1932 "#ifdef FRAGMENT_SHADER\n"
1933 "\n"
1934 "void main\n"
1935 "(\n"
1936 "float2 TexCoord : TEXCOORD0,\n"
1937 "uniform sampler2D Texture_First,\n"
1938 "uniform float4 BloomBlur_Parameters,\n"
1939 "out float4 gl_FragColor : COLOR\n"
1940 ")\n"
1941 "{\n"
1942 "       int i;\n"
1943 "       float2 tc = TexCoord;\n"
1944 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
1945 "       tc += BloomBlur_Parameters.xy;\n"
1946 "       for (i = 1;i < SAMPLES;i++)\n"
1947 "       {\n"
1948 "               color += tex2D(Texture_First, tc).rgb;\n"
1949 "               tc += BloomBlur_Parameters.xy;\n"
1950 "       }\n"
1951 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
1952 "}\n"
1953 "#endif\n"
1954 "#else // !MODE_BLOOMBLUR\n"
1955 "#ifdef MODE_REFRACTION\n"
1956 "#ifdef VERTEX_SHADER\n"
1957 "void main\n"
1958 "(\n"
1959 "float4 gl_Vertex : POSITION,\n"
1960 "uniform float4x4 ModelViewProjectionMatrix,\n"
1961 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1962 "uniform mat4 TexMatrix,\n"
1963 "uniform float3 EyePosition,\n"
1964 "out float4 gl_Position : POSITION,\n"
1965 "out float2 TexCoord : TEXCOORD0,\n"
1966 "out float3 EyeVector : TEXCOORD1,\n"
1967 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
1968 ")\n"
1969 "{\n"
1970 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
1971 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1972 "       ModelViewProjectionPosition = gl_Position;\n"
1973 "}\n"
1974 "#endif\n"
1975 "\n"
1976 "#ifdef FRAGMENT_SHADER\n"
1977 "void main\n"
1978 "(\n"
1979 "float2 TexCoord : TEXCOORD0,\n"
1980 "float3 EyeVector : TEXCOORD1,\n"
1981 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
1982 "uniform sampler2D Texture_Normal,\n"
1983 "uniform sampler2D Texture_Refraction,\n"
1984 "uniform sampler2D Texture_Reflection,\n"
1985 "uniform float4 DistortScaleRefractReflect,\n"
1986 "uniform float4 ScreenScaleRefractReflect,\n"
1987 "uniform float4 ScreenCenterRefractReflect,\n"
1988 "uniform float4 RefractColor,\n"
1989 "out float4 gl_FragColor : COLOR\n"
1990 ")\n"
1991 "{\n"
1992 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
1993 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1994 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1995 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
1996 "       // FIXME temporary hack to detect the case that the reflection\n"
1997 "       // gets blackened at edges due to leaving the area that contains actual\n"
1998 "       // content.\n"
1999 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2000 "       // 'appening.\n"
2001 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2002 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2003 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2004 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2005 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2006 "       gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2007 "}\n"
2008 "#endif\n"
2009 "#else // !MODE_REFRACTION\n"
2010 "\n"
2011 "\n"
2012 "\n"
2013 "\n"
2014 "#ifdef MODE_WATER\n"
2015 "#ifdef VERTEX_SHADER\n"
2016 "\n"
2017 "void main\n"
2018 "(\n"
2019 "float4 gl_Vertex : POSITION,\n"
2020 "uniform float4x4 ModelViewProjectionMatrix,\n"
2021 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2022 "uniform mat4 TexMatrix,\n"
2023 "uniform float3 EyePosition,\n"
2024 "out float4 gl_Position : POSITION,\n"
2025 "out float2 TexCoord : TEXCOORD0,\n"
2026 "out float3 EyeVector : TEXCOORD1,\n"
2027 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2028 ")\n"
2029 "{\n"
2030 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2031 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2032 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2033 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2034 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2035 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2036 "       ModelViewProjectionPosition = gl_Position;\n"
2037 "}\n"
2038 "#endif\n"
2039 "\n"
2040 "#ifdef FRAGMENT_SHADER\n"
2041 "void main\n"
2042 "(\n"
2043 "float2 TexCoord : TEXCOORD0,\n"
2044 "float3 EyeVector : TEXCOORD1,\n"
2045 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2046 "uniform sampler2D Texture_Normal,\n"
2047 "uniform sampler2D Texture_Refraction,\n"
2048 "uniform sampler2D Texture_Reflection,\n"
2049 "uniform float4 DistortScaleRefractReflect,\n"
2050 "uniform float4 ScreenScaleRefractReflect,\n"
2051 "uniform float4 ScreenCenterRefractReflect,\n"
2052 "uniform float4 RefractColor,\n"
2053 "uniform float4 ReflectColor,\n"
2054 "uniform float ReflectFactor,\n"
2055 "uniform float ReflectOffset,\n"
2056 "out float4 gl_FragColor : COLOR\n"
2057 ")\n"
2058 "{\n"
2059 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2060 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2061 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2062 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xyxy * DistortScaleRefractReflect;\n"
2063 "       // FIXME temporary hack to detect the case that the reflection\n"
2064 "       // gets blackened at edges due to leaving the area that contains actual\n"
2065 "       // content.\n"
2066 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2067 "       // 'appening.\n"
2068 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2069 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2070 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2071 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2072 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2073 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2074 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2075 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2076 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2077 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2078 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2079 "       gl_FragColor = mix(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2080 "}\n"
2081 "#endif\n"
2082 "#else // !MODE_WATER\n"
2083 "\n"
2084 "\n"
2085 "\n"
2086 "\n"
2087 "// 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"
2088 "\n"
2089 "// fragment shader specific:\n"
2090 "#ifdef FRAGMENT_SHADER\n"
2091 "\n"
2092 "#ifdef USEFOG\n"
2093 "float FogVertex(float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask)\n"
2094 "{\n"
2095 "       float fogfrac;\n"
2096 "#ifdef USEFOGOUTSIDE\n"
2097 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2098 "#else\n"
2099 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2100 "#endif\n"
2101 "       return float(tex2D(Texture_FogMask, half2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
2102 "}\n"
2103 "#endif\n"
2104 "\n"
2105 "#ifdef USEOFFSETMAPPING\n"
2106 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler2D Texture_Normal)\n"
2107 "{\n"
2108 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2109 "       // 14 sample relief mapping: linear search and then binary search\n"
2110 "       // this basically steps forward a small amount repeatedly until it finds\n"
2111 "       // itself inside solid, then jitters forward and back using decreasing\n"
2112 "       // amounts to find the impact\n"
2113 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2114 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2115 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2116 "       float3 RT = float3(TexCoord, 1);\n"
2117 "       OffsetVector *= 0.1;\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);\n"
2121 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2122 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2123 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2124 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2125 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2126 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2127 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2128 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2129 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2130 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2131 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2132 "       return RT.xy;\n"
2133 "#else\n"
2134 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2135 "       // this basically moves forward the full distance, and then backs up based\n"
2136 "       // on height of samples\n"
2137 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2138 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2139 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2140 "       TexCoord += OffsetVector;\n"
2141 "       OffsetVector *= 0.333;\n"
2142 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2143 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2144 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2145 "       return TexCoord;\n"
2146 "#endif\n"
2147 "}\n"
2148 "#endif // USEOFFSETMAPPING\n"
2149 "\n"
2150 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2151 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2152 "# ifndef USESHADOWMAPVSDCT\n"
2153 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2154 "{\n"
2155 "       float3 adir = abs(dir);\n"
2156 "       float2 tc;\n"
2157 "       float2 offset;\n"
2158 "       float ma;\n"
2159 "       if (adir.x > adir.y)\n"
2160 "       {\n"
2161 "               if (adir.x > adir.z) // X\n"
2162 "               {\n"
2163 "                       ma = adir.x;\n"
2164 "                       tc = dir.zy;\n"
2165 "                       offset = float2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
2166 "               }\n"
2167 "               else // Z\n"
2168 "               {\n"
2169 "                       ma = adir.z;\n"
2170 "                       tc = dir.xy;\n"
2171 "                       offset = float2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
2172 "               }\n"
2173 "       }\n"
2174 "       else\n"
2175 "       {\n"
2176 "               if (adir.y > adir.z) // Y\n"
2177 "               {\n"
2178 "                       ma = adir.y;\n"
2179 "                       tc = dir.xz;\n"
2180 "                       offset = float2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
2181 "               }\n"
2182 "               else // Z\n"
2183 "               {\n"
2184 "                       ma = adir.z;\n"
2185 "                       tc = dir.xy;\n"
2186 "                       offset = float2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
2187 "               }\n"
2188 "       }\n"
2189 "\n"
2190 "       float3 stc = float3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2191 "       stc.xy += offset * ShadowMap_Parameters.y;\n"
2192 "       stc.z += ShadowMap_Parameters.z;\n"
2193 "       return stc;\n"
2194 "}\n"
2195 "# else\n"
2196 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2197 "{\n"
2198 "       float3 adir = abs(dir);\n"
2199 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2200 "       float ma = max(max(adir.x, adir.y), adir.z);\n"
2201 "       float3 stc = float3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2202 "       stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
2203 "       stc.z += ShadowMap_Parameters.z;\n"
2204 "       return stc;\n"
2205 "}\n"
2206 "# endif\n"
2207 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2208 "\n"
2209 "#ifdef USESHADOWMAPCUBE\n"
2210 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2211 "{\n"
2212 "    float3 adir = abs(dir);\n"
2213 "    return float4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
2214 "}\n"
2215 "#endif\n"
2216 "\n"
2217 "# ifdef USESHADOWMAPRECT\n"
2218 "#ifdef USESHADOWMAPVSDCT\n"
2219 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2220 "#else\n"
2221 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2222 "#endif\n"
2223 "{\n"
2224 "#ifdef USESHADOWMAPVSDCT\n"
2225 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2226 "#else\n"
2227 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2228 "#endif\n"
2229 "       float f;\n"
2230 "#  ifdef USESHADOWSAMPLER\n"
2231 "\n"
2232 "#    ifdef USESHADOWMAPPCF\n"
2233 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2234 "    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"
2235 "#    else\n"
2236 "    f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2237 "#    endif\n"
2238 "\n"
2239 "#  else\n"
2240 "\n"
2241 "#    ifdef USESHADOWMAPPCF\n"
2242 "#      if USESHADOWMAPPCF > 1\n"
2243 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2244 "    float2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
2245 "    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"
2246 "    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"
2247 "    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"
2248 "    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"
2249 "    float4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
2250 "    f = dot(mix(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2251 "#      else\n"
2252 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2253 "    float2 offset = fract(shadowmaptc.xy);\n"
2254 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2255 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2256 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2257 "    float3 cols = row2 + mix(row1, row3, offset.y);\n"
2258 "    f = dot(mix(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2259 "#      endif\n"
2260 "#    else\n"
2261 "    f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2262 "#    endif\n"
2263 "\n"
2264 "#  endif\n"
2265 "       return f;\n"
2266 "}\n"
2267 "# endif\n"
2268 "\n"
2269 "# ifdef USESHADOWMAP2D\n"
2270 "#ifdef USESHADOWMAPVSDCT\n"
2271 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2272 "#else\n"
2273 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2274 "#endif\n"
2275 "{\n"
2276 "#ifdef USESHADOWMAPVSDCT\n"
2277 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2278 "#else\n"
2279 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2280 "#endif\n"
2281 "    float f;\n"
2282 "\n"
2283 "#  ifdef USESHADOWSAMPLER\n"
2284 "#    ifdef USESHADOWMAPPCF\n"
2285 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, float3(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
2286 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2287 "    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"
2288 "#    else\n"
2289 "    f = shadow2D(Texture_ShadowMap2D, float3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
2290 "#    endif\n"
2291 "#  else\n"
2292 "#    ifdef USESHADOWMAPPCF\n"
2293 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2294 "#      ifdef GL_ARB_texture_gather\n"
2295 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
2296 "#      else\n"
2297 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x,y)*ShadowMap_TextureScale)\n"
2298 "#      endif\n"
2299 "    float2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
2300 "    center *= ShadowMap_TextureScale;\n"
2301 "    float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2302 "    float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2303 "    float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2304 "    float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2305 "    float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2306 "                mix(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2307 "    f = dot(mix(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2308 "#     else\n"
2309 "#      ifdef GL_EXT_gpu_shader4\n"
2310 "#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, ifloat2(x, y)).r\n"
2311 "#      else\n"
2312 "#        define texval(x, y) tex2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
2313 "#      endif\n"
2314 "#      if USESHADOWMAPPCF > 1\n"
2315 "    float2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
2316 "    center *= ShadowMap_TextureScale;\n"
2317 "    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"
2318 "    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"
2319 "    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"
2320 "    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"
2321 "    float4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
2322 "    f = dot(mix(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2323 "#      else\n"
2324 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
2325 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2326 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2327 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2328 "    float3 cols = row2 + mix(row1, row3, offset.y);\n"
2329 "    f = dot(mix(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2330 "#      endif\n"
2331 "#     endif\n"
2332 "#    else\n"
2333 "    f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2334 "#    endif\n"
2335 "#  endif\n"
2336 "    return f;\n"
2337 "}\n"
2338 "# endif\n"
2339 "\n"
2340 "# ifdef USESHADOWMAPCUBE\n"
2341 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2342 "{\n"
2343 "    // apply depth texture cubemap as light filter\n"
2344 "    float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2345 "    float f;\n"
2346 "#  ifdef USESHADOWSAMPLER\n"
2347 "    f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2348 "#  else\n"
2349 "    f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2350 "#  endif\n"
2351 "    return f;\n"
2352 "}\n"
2353 "# endif\n"
2354 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2355 "#endif // FRAGMENT_SHADER\n"
2356 "\n"
2357 "\n"
2358 "\n"
2359 "\n"
2360 "#ifdef MODE_DEFERREDGEOMETRY\n"
2361 "#ifdef VERTEX_SHADER\n"
2362 "void main\n"
2363 "(\n"
2364 "float4 gl_Vertex : POSITION,\n"
2365 "uniform float4x4 ModelViewProjectionMatrix,\n"
2366 "#ifdef USEVERTEXTEXTUREBLEND\n"
2367 "float4 gl_Color : COLOR0,\n"
2368 "#endif\n"
2369 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2370 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2371 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2372 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2373 "uniform mat4 TexMatrix,\n"
2374 "#ifdef USEVERTEXTEXTUREBLEND\n"
2375 "uniform mat4 BackgroundTexMatrix,\n"
2376 "#endif\n"
2377 "uniform mat4 ModelViewMatrix,\n"
2378 "out float4 gl_Position : POSITION,\n"
2379 "out float4 gl_FrontColor : COLOR,\n"
2380 "out float4 TexCoordBoth : TEXCOORD0,\n"
2381 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2382 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2383 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2384 ")\n"
2385 "{\n"
2386 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2387 "#ifdef USEVERTEXTEXTUREBLEND\n"
2388 "       gl_FrontColor = gl_Color;\n"
2389 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2390 "#endif\n"
2391 "\n"
2392 "       // transform unnormalized eye direction into tangent space\n"
2393 "#ifdef USEOFFSETMAPPING\n"
2394 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2395 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2396 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2397 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2398 "#endif\n"
2399 "\n"
2400 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2401 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2402 "       VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2403 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2404 "}\n"
2405 "#endif // VERTEX_SHADER\n"
2406 "\n"
2407 "#ifdef FRAGMENT_SHADER\n"
2408 "void main\n"
2409 "(\n"
2410 "float4 TexCoordBoth : TEXCOORD0,\n"
2411 "float3 EyeVector : TEXCOORD2,\n"
2412 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2413 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2414 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2415 "uniform sampler2D Texture_Normal,\n"
2416 "#ifdef USEALPHAKILL\n"
2417 "uniform sampler2D Texture_Color,\n"
2418 "#endif\n"
2419 "#ifdef USEVERTEXTEXTUREBLEND\n"
2420 "uniform sampler2D Texture_SecondaryNormal,\n"
2421 "#endif\n"
2422 "#ifdef USEOFFSETMAPPING\n"
2423 "uniform float OffsetMapping_Scale,\n"
2424 "#endif\n"
2425 "uniform half SpecularPower,\n"
2426 "out float4 gl_FragColor : COLOR\n"
2427 ")\n"
2428 "{\n"
2429 "       float2 TexCoord = TexCoordBoth.xy;\n"
2430 "#ifdef USEOFFSETMAPPING\n"
2431 "       // apply offsetmapping\n"
2432 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2433 "#define TexCoord TexCoordOffset\n"
2434 "#endif\n"
2435 "\n"
2436 "#ifdef USEALPHAKILL\n"
2437 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2438 "               discard;\n"
2439 "#endif\n"
2440 "\n"
2441 "#ifdef USEVERTEXTEXTUREBLEND\n"
2442 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2443 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2444 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2445 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2446 "#endif\n"
2447 "\n"
2448 "#ifdef USEVERTEXTEXTUREBLEND\n"
2449 "       float3 surfacenormal = mix(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
2450 "#else\n"
2451 "       float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
2452 "#endif\n"
2453 "\n"
2454 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), 1);\n"
2455 "}\n"
2456 "#endif // FRAGMENT_SHADER\n"
2457 "#else // !MODE_DEFERREDGEOMETRY\n"
2458 "\n"
2459 "\n"
2460 "\n"
2461 "\n"
2462 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2463 "#ifdef VERTEX_SHADER\n"
2464 "void main\n"
2465 "(\n"
2466 "float4 gl_Vertex : POSITION,\n"
2467 "uniform float4x4 ModelViewProjectionMatrix,\n"
2468 "uniform mat4 ModelViewMatrix,\n"
2469 "out float4 gl_Position : POSITION,\n"
2470 "out float4 ModelViewPosition : TEXCOORD0\n"
2471 ")\n"
2472 "{\n"
2473 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2474 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2475 "}\n"
2476 "#endif // VERTEX_SHADER\n"
2477 "\n"
2478 "#ifdef FRAGMENT_SHADER\n"
2479 "void main\n"
2480 "(\n"
2481 "float2 Pixel : WPOS,\n"
2482 "float4 ModelViewPosition : TEXCOORD0,\n"
2483 "uniform mat4 ViewToLight,\n"
2484 "uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2485 "uniform float3 LightPosition,\n"
2486 "uniform half3 DeferredColor_Ambient,\n"
2487 "uniform half3 DeferredColor_Diffuse,\n"
2488 "#ifdef USESPECULAR\n"
2489 "uniform half3 DeferredColor_Specular,\n"
2490 "uniform half SpecularPower,\n"
2491 "#endif\n"
2492 "uniform sampler2D Texture_Attenuation,\n"
2493 "uniform samplerRECT Texture_ScreenDepth,\n"
2494 "uniform samplerRECT Texture_ScreenNormalMap,\n"
2495 "\n"
2496 "#ifdef USESHADOWMAPRECT\n"
2497 "# ifdef USESHADOWSAMPLER\n"
2498 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2499 "# else\n"
2500 "uniform samplerRECT Texture_ShadowMapRect,\n"
2501 "# endif\n"
2502 "#endif\n"
2503 "\n"
2504 "#ifdef USESHADOWMAP2D\n"
2505 "# ifdef USESHADOWSAMPLER\n"
2506 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2507 "# else\n"
2508 "uniform sampler2D Texture_ShadowMap2D,\n"
2509 "# endif\n"
2510 "#endif\n"
2511 "\n"
2512 "#ifdef USESHADOWMAPVSDCT\n"
2513 "uniform samplerCUBE Texture_CubeProjection,\n"
2514 "#endif\n"
2515 "\n"
2516 "#ifdef USESHADOWMAPCUBE\n"
2517 "# ifdef USESHADOWSAMPLER\n"
2518 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2519 "# else\n"
2520 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2521 "# endif\n"
2522 "#endif\n"
2523 "\n"
2524 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2525 "uniform float2 ShadowMap_TextureScale,\n"
2526 "uniform float4 ShadowMap_Parameters,\n"
2527 "#endif\n"
2528 "\n"
2529 "out float4 gl_FragData0 : COLOR0,\n"
2530 "out float4 gl_FragData1 : COLOR1\n"
2531 ")\n"
2532 "{\n"
2533 "       // calculate viewspace pixel position\n"
2534 "       float3 position;\n"
2535 "       position.z = ScreenToDepth.y / (texRECT(Texture_ScreenDepth, Pixel).r + ScreenToDepth.x);\n"
2536 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2537 "       // decode viewspace pixel normal\n"
2538 "       half4 normalmap = texRECT(Texture_ScreenNormalMap, Pixel);\n"
2539 "       half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
2540 "       // surfacenormal = pixel normal in viewspace\n"
2541 "       // LightVector = pixel to light in viewspace\n"
2542 "       // CubeVector = position in lightspace\n"
2543 "       // eyevector = pixel to view in viewspace\n"
2544 "       float3 CubeVector = float3(mul(ViewToLight, float4(position,1)));\n"
2545 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2546 "#ifdef USEDIFFUSE\n"
2547 "       // calculate diffuse shading\n"
2548 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2549 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2550 "#endif\n"
2551 "#ifdef USESPECULAR\n"
2552 "       // calculate directional shading\n"
2553 "       float3 eyevector = position * -1.0;\n"
2554 "#  ifdef USEEXACTSPECULARMATH\n"
2555 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
2556 "#  else\n"
2557 "       half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
2558 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
2559 "#  endif\n"
2560 "#endif\n"
2561 "\n"
2562 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2563 "       fade *= ShadowMapCompare(CubeVector,\n"
2564 "# if defined(USESHADOWMAP2D)\n"
2565 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2566 "# endif\n"
2567 "# if defined(USESHADOWMAPRECT)\n"
2568 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2569 "# endif\n"
2570 "# if defined(USESHADOWMAPCUBE)\n"
2571 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2572 "# endif\n"
2573 "\n"
2574 "#ifdef USESHADOWMAPVSDCT\n"
2575 ", Texture_CubeProjection\n"
2576 "#endif\n"
2577 "       );\n"
2578 "#endif\n"
2579 "\n"
2580 "#ifdef USEDIFFUSE\n"
2581 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2582 "#else\n"
2583 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2584 "#endif\n"
2585 "#ifdef USESPECULAR\n"
2586 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2587 "#else\n"
2588 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2589 "#endif\n"
2590 "\n"
2591 "# ifdef USECUBEFILTER\n"
2592 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2593 "       gl_FragData0.rgb *= cubecolor;\n"
2594 "       gl_FragData1.rgb *= cubecolor;\n"
2595 "# endif\n"
2596 "}\n"
2597 "#endif // FRAGMENT_SHADER\n"
2598 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2599 "\n"
2600 "\n"
2601 "\n"
2602 "\n"
2603 "#ifdef VERTEX_SHADER\n"
2604 "void main\n"
2605 "(\n"
2606 "float4 gl_Vertex : POSITION,\n"
2607 "uniform float4x4 ModelViewProjectionMatrix,\n"
2608 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2609 "float4 gl_Color : COLOR0,\n"
2610 "#endif\n"
2611 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2612 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2613 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2614 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2615 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2616 "\n"
2617 "uniform float3 EyePosition,\n"
2618 "uniform mat4 TexMatrix,\n"
2619 "#ifdef USEVERTEXTEXTUREBLEND\n"
2620 "uniform mat4 BackgroundTexMatrix,\n"
2621 "#endif\n"
2622 "#ifdef MODE_LIGHTSOURCE\n"
2623 "uniform mat4 ModelToLight,\n"
2624 "#endif\n"
2625 "#ifdef MODE_LIGHTSOURCE\n"
2626 "uniform float3 LightPosition,\n"
2627 "#endif\n"
2628 "#ifdef MODE_LIGHTDIRECTION\n"
2629 "uniform float3 LightDir,\n"
2630 "#endif\n"
2631 "uniform float4 FogPlane,\n"
2632 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2633 "uniform float3 LightPosition,\n"
2634 "#endif\n"
2635 "\n"
2636 "out float4 gl_FrontColor : COLOR,\n"
2637 "out float4 TexCoordBoth : TEXCOORD0,\n"
2638 "#ifdef USELIGHTMAP\n"
2639 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2640 "#endif\n"
2641 "#ifdef USEEYEVECTOR\n"
2642 "out float3 EyeVector : TEXCOORD2,\n"
2643 "#endif\n"
2644 "#ifdef USEREFLECTION\n"
2645 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2646 "#endif\n"
2647 "#ifdef USEFOG\n"
2648 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2649 "#endif\n"
2650 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2651 "out float3 LightVector : TEXCOORD5,\n"
2652 "#endif\n"
2653 "#ifdef MODE_LIGHTSOURCE\n"
2654 "out float3 CubeVector : TEXCOORD3,\n"
2655 "#endif\n"
2656 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
2657 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2658 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2659 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2660 "#endif\n"
2661 "out float4 gl_Position : POSITION\n"
2662 ")\n"
2663 "{\n"
2664 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2665 "       gl_FrontColor = gl_Color;\n"
2666 "#endif\n"
2667 "       // copy the surface texcoord\n"
2668 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2669 "#ifdef USEVERTEXTEXTUREBLEND\n"
2670 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2671 "#endif\n"
2672 "#ifdef USELIGHTMAP\n"
2673 "       TexCoordLightmap = float2(gl_MultiTexCoord4);\n"
2674 "#endif\n"
2675 "\n"
2676 "#ifdef MODE_LIGHTSOURCE\n"
2677 "       // transform vertex position into light attenuation/cubemap space\n"
2678 "       // (-1 to +1 across the light box)\n"
2679 "       CubeVector = float3(mul(ModelToLight, gl_Vertex));\n"
2680 "\n"
2681 "# ifdef USEDIFFUSE\n"
2682 "       // transform unnormalized light direction into tangent space\n"
2683 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2684 "       //  normalize it per pixel)\n"
2685 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2686 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2687 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2688 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2689 "# endif\n"
2690 "#endif\n"
2691 "\n"
2692 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2693 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2694 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2695 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2696 "#endif\n"
2697 "\n"
2698 "       // transform unnormalized eye direction into tangent space\n"
2699 "#ifdef USEEYEVECTOR\n"
2700 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2701 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2702 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2703 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2704 "#endif\n"
2705 "\n"
2706 "#ifdef USEFOG\n"
2707 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2708 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2709 "#endif\n"
2710 "\n"
2711 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2712 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2713 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2714 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2715 "#endif\n"
2716 "\n"
2717 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2718 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2719 "\n"
2720 "#ifdef USEREFLECTION\n"
2721 "       ModelViewProjectionPosition = gl_Position;\n"
2722 "#endif\n"
2723 "}\n"
2724 "#endif // VERTEX_SHADER\n"
2725 "\n"
2726 "\n"
2727 "\n"
2728 "\n"
2729 "#ifdef FRAGMENT_SHADER\n"
2730 "void main\n"
2731 "(\n"
2732 "#ifdef USEDEFERREDLIGHTMAP\n"
2733 "float2 Pixel : WPOS,\n"
2734 "#endif\n"
2735 "float4 gl_FrontColor : COLOR,\n"
2736 "float4 TexCoordBoth : TEXCOORD0,\n"
2737 "#ifdef USELIGHTMAP\n"
2738 "float2 TexCoordLightmap : TEXCOORD1,\n"
2739 "#endif\n"
2740 "#ifdef USEEYEVECTOR\n"
2741 "float3 EyeVector : TEXCOORD2,\n"
2742 "#endif\n"
2743 "#ifdef USEREFLECTION\n"
2744 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2745 "#endif\n"
2746 "#ifdef USEFOG\n"
2747 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2748 "#endif\n"
2749 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2750 "float3 LightVector : TEXCOORD5,\n"
2751 "#endif\n"
2752 "#ifdef MODE_LIGHTSOURCE\n"
2753 "float3 CubeVector : TEXCOORD3,\n"
2754 "#endif\n"
2755 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2756 "float4 ModelViewPosition : TEXCOORD0,\n"
2757 "#endif\n"
2758 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
2759 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2760 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2761 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2762 "#endif\n"
2763 "\n"
2764 "uniform sampler2D Texture_Normal,\n"
2765 "uniform sampler2D Texture_Color,\n"
2766 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2767 "uniform sampler2D Texture_Gloss,\n"
2768 "#endif\n"
2769 "#ifdef USEGLOW\n"
2770 "uniform sampler2D Texture_Glow,\n"
2771 "#endif\n"
2772 "#ifdef USEVERTEXTEXTUREBLEND\n"
2773 "uniform sampler2D Texture_SecondaryNormal,\n"
2774 "uniform sampler2D Texture_SecondaryColor,\n"
2775 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2776 "uniform sampler2D Texture_SecondaryGloss,\n"
2777 "#endif\n"
2778 "#ifdef USEGLOW\n"
2779 "uniform sampler2D Texture_SecondaryGlow,\n"
2780 "#endif\n"
2781 "#endif\n"
2782 "#ifdef USECOLORMAPPING\n"
2783 "uniform sampler2D Texture_Pants,\n"
2784 "uniform sampler2D Texture_Shirt,\n"
2785 "#endif\n"
2786 "#ifdef USEFOG\n"
2787 "uniform sampler2D Texture_FogMask,\n"
2788 "#endif\n"
2789 "#ifdef USELIGHTMAP\n"
2790 "uniform sampler2D Texture_Lightmap,\n"
2791 "#endif\n"
2792 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2793 "uniform sampler2D Texture_Deluxemap,\n"
2794 "#endif\n"
2795 "#ifdef USEREFLECTION\n"
2796 "uniform sampler2D Texture_Reflection,\n"
2797 "#endif\n"
2798 "\n"
2799 "//#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2800 "uniform samplerRECT Texture_ScreenDepth,\n"
2801 "uniform samplerRECT Texture_ScreenNormalMap,\n"
2802 "//#endif\n"
2803 "#ifdef USEDEFERREDLIGHTMAP\n"
2804 "uniform samplerRECT Texture_ScreenDiffuse,\n"
2805 "uniform samplerRECT Texture_ScreenSpecular,\n"
2806 "#endif\n"
2807 "\n"
2808 "#ifdef USECOLORMAPPING\n"
2809 "uniform half3 Color_Pants,\n"
2810 "uniform half3 Color_Shirt,\n"
2811 "#endif\n"
2812 "#ifdef USEFOG\n"
2813 "uniform float3 FogColor,\n"
2814 "uniform float FogRangeRecip,\n"
2815 "uniform float FogPlaneViewDist,\n"
2816 "uniform float FogHeightFade,\n"
2817 "#endif\n"
2818 "\n"
2819 "#ifdef USEOFFSETMAPPING\n"
2820 "uniform float OffsetMapping_Scale,\n"
2821 "#endif\n"
2822 "\n"
2823 "#ifdef USEDEFERREDLIGHTMAP\n"
2824 "uniform half3 DeferredMod_Diffuse,\n"
2825 "uniform half3 DeferredMod_Specular,\n"
2826 "#endif\n"
2827 "uniform half3 Color_Ambient,\n"
2828 "uniform half3 Color_Diffuse,\n"
2829 "uniform half3 Color_Specular,\n"
2830 "uniform half SpecularPower,\n"
2831 "#ifdef USEGLOW\n"
2832 "uniform half3 Color_Glow,\n"
2833 "#endif\n"
2834 "uniform half Alpha,\n"
2835 "#ifdef USEREFLECTION\n"
2836 "uniform float4 DistortScaleRefractReflect,\n"
2837 "uniform float4 ScreenScaleRefractReflect,\n"
2838 "uniform float4 ScreenCenterRefractReflect,\n"
2839 "uniform half4 ReflectColor,\n"
2840 "#endif\n"
2841 "#ifdef MODE_LIGHTDIRECTION\n"
2842 "uniform half3 LightColor,\n"
2843 "#endif\n"
2844 "#ifdef MODE_LIGHTSOURCE\n"
2845 "uniform half3 LightColor,\n"
2846 "#endif\n"
2847 "\n"
2848 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2849 "uniform sampler2D Texture_Attenuation,\n"
2850 "uniform samplerCUBE Texture_Cube,\n"
2851 "\n"
2852 "#ifdef USESHADOWMAPRECT\n"
2853 "# ifdef USESHADOWSAMPLER\n"
2854 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2855 "# else\n"
2856 "uniform samplerRECT Texture_ShadowMapRect,\n"
2857 "# endif\n"
2858 "#endif\n"
2859 "\n"
2860 "#ifdef USESHADOWMAP2D\n"
2861 "# ifdef USESHADOWSAMPLER\n"
2862 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2863 "# else\n"
2864 "uniform sampler2D Texture_ShadowMap2D,\n"
2865 "# endif\n"
2866 "#endif\n"
2867 "\n"
2868 "#ifdef USESHADOWMAPVSDCT\n"
2869 "uniform samplerCUBE Texture_CubeProjection,\n"
2870 "#endif\n"
2871 "\n"
2872 "#ifdef USESHADOWMAPCUBE\n"
2873 "# ifdef USESHADOWSAMPLER\n"
2874 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2875 "# else\n"
2876 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2877 "# endif\n"
2878 "#endif\n"
2879 "\n"
2880 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2881 "uniform float2 ShadowMap_TextureScale,\n"
2882 "uniform float4 ShadowMap_Parameters,\n"
2883 "#endif\n"
2884 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2885 "\n"
2886 "out float4 gl_FragColor : COLOR\n"
2887 ")\n"
2888 "{\n"
2889 "       float2 TexCoord = TexCoordBoth.xy;\n"
2890 "#ifdef USEVERTEXTEXTUREBLEND\n"
2891 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
2892 "#endif\n"
2893 "#ifdef USEOFFSETMAPPING\n"
2894 "       // apply offsetmapping\n"
2895 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2896 "#define TexCoord TexCoordOffset\n"
2897 "#endif\n"
2898 "\n"
2899 "       // combine the diffuse textures (base, pants, shirt)\n"
2900 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
2901 "#ifdef USEALPHAKILL\n"
2902 "       if (color.a < 0.5)\n"
2903 "               discard;\n"
2904 "#endif\n"
2905 "       color.a *= Alpha;\n"
2906 "#ifdef USECOLORMAPPING\n"
2907 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord)) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
2908 "#endif\n"
2909 "#ifdef USEVERTEXTEXTUREBLEND\n"
2910 "       float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
2911 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
2912 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
2913 "       color.rgb = half3(mix(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
2914 "       color.a = 1.0;\n"
2915 "       //color = mix(half4(1, 0, 0, 1), color, terrainblend);\n"
2916 "#endif\n"
2917 "\n"
2918 "       // get the surface normal\n"
2919 "#ifdef USEVERTEXTEXTUREBLEND\n"
2920 "       half3 surfacenormal = normalize(half3(mix(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
2921 "#else\n"
2922 "       half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
2923 "#endif\n"
2924 "\n"
2925 "       // get the material colors\n"
2926 "       half3 diffusetex = color.rgb;\n"
2927 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2928 "# ifdef USEVERTEXTEXTUREBLEND\n"
2929 "       half3 glosstex = half3(mix(float3(tex2D(Texture_SecondaryGloss, TexCoord2)), float3(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
2930 "# else\n"
2931 "       half3 glosstex = half3(tex2D(Texture_Gloss, TexCoord));\n"
2932 "# endif\n"
2933 "#endif\n"
2934 "\n"
2935 "\n"
2936 "\n"
2937 "\n"
2938 "#ifdef MODE_LIGHTSOURCE\n"
2939 "       // light source\n"
2940 "       half3 lightnormal = half3(normalize(LightVector));\n"
2941 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2942 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
2943 "#ifdef USESPECULAR\n"
2944 "#ifdef USEEXACTSPECULARMATH\n"
2945 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
2946 "#else\n"
2947 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
2948 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
2949 "#endif\n"
2950 "       color.rgb += glosstex * (specular * Color_Specular);\n"
2951 "#endif\n"
2952 "       color.rgb *= LightColor;\n"
2953 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2954 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
2955 "       color.rgb *= ShadowMapCompare(CubeVector,\n"
2956 "# if defined(USESHADOWMAP2D)\n"
2957 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2958 "# endif\n"
2959 "# if defined(USESHADOWMAPRECT)\n"
2960 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2961 "# endif\n"
2962 "# if defined(USESHADOWMAPCUBE)\n"
2963 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2964 "# endif\n"
2965 "\n"
2966 "#ifdef USESHADOWMAPVSDCT\n"
2967 ", Texture_CubeProjection\n"
2968 "#endif\n"
2969 "       );\n"
2970 "\n"
2971 "#endif\n"
2972 "# ifdef USECUBEFILTER\n"
2973 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector));\n"
2974 "# endif\n"
2975 "#endif // MODE_LIGHTSOURCE\n"
2976 "\n"
2977 "\n"
2978 "\n"
2979 "\n"
2980 "#ifdef MODE_LIGHTDIRECTION\n"
2981 "#define SHADING\n"
2982 "#ifdef USEDIFFUSE\n"
2983 "       half3 lightnormal = half3(normalize(LightVector));\n"
2984 "#endif\n"
2985 "#define lightcolor LightColor\n"
2986 "#endif // MODE_LIGHTDIRECTION\n"
2987 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2988 "#define SHADING\n"
2989 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
2990 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
2991 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
2992 "       // convert modelspace light vector to tangentspace\n"
2993 "       half3 lightnormal;\n"
2994 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
2995 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
2996 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
2997 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
2998 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
2999 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3000 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3001 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3002 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3003 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3004 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3005 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3006 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3007 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3008 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3009 "#define SHADING\n"
3010 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3011 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3012 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3013 "#endif\n"
3014 "\n"
3015 "\n"
3016 "\n"
3017 "\n"
3018 "#ifdef MODE_LIGHTMAP\n"
3019 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
3020 "#endif // MODE_LIGHTMAP\n"
3021 "#ifdef MODE_VERTEXCOLOR\n"
3022 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3023 "#endif // MODE_VERTEXCOLOR\n"
3024 "#ifdef MODE_FLATCOLOR\n"
3025 "       color.rgb = diffusetex * Color_Ambient;\n"
3026 "#endif // MODE_FLATCOLOR\n"
3027 "\n"
3028 "\n"
3029 "\n"
3030 "\n"
3031 "#ifdef SHADING\n"
3032 "# ifdef USEDIFFUSE\n"
3033 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3034 "#  ifdef USESPECULAR\n"
3035 "#   ifdef USEEXACTSPECULARMATH\n"
3036 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
3037 "#   else\n"
3038 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3039 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
3040 "#   endif\n"
3041 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
3042 "#  else\n"
3043 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3044 "#  endif\n"
3045 "# else\n"
3046 "       color.rgb = diffusetex * Color_Ambient;\n"
3047 "# endif\n"
3048 "#endif\n"
3049 "\n"
3050 "#ifdef USEDEFERREDLIGHTMAP\n"
3051 "       color.rgb += diffusetex * half3(texRECT(Texture_ScreenDiffuse, Pixel)) * DeferredMod_Diffuse;\n"
3052 "       color.rgb += glosstex * half3(texRECT(Texture_ScreenSpecular, Pixel)) * DeferredMod_Specular;\n"
3053 "       color.rgb = half3(texRECT(Texture_ScreenDepth, Pixel));\n"
3054 "#endif\n"
3055 "\n"
3056 "#ifdef USEGLOW\n"
3057 "#ifdef USEVERTEXTEXTUREBLEND\n"
3058 "       color.rgb += mix(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
3059 "#else\n"
3060 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
3061 "#endif\n"
3062 "#endif\n"
3063 "\n"
3064 "#ifdef USEFOG\n"
3065 "#ifdef MODE_LIGHTSOURCE\n"
3066 "       color.rgb *= half(FogVertex());\n"
3067 "#else\n"
3068 "       color.rgb = mix(FogColor, float3(color.rgb), FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3069 "#endif\n"
3070 "#endif\n"
3071 "\n"
3072 "       // 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"
3073 "#ifdef USEREFLECTION\n"
3074 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3075 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3076 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3077 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
3078 "       // FIXME temporary hack to detect the case that the reflection\n"
3079 "       // gets blackened at edges due to leaving the area that contains actual\n"
3080 "       // content.\n"
3081 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3082 "       // 'appening.\n"
3083 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3084 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3085 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3086 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3087 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3088 "       color.rgb = mix(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
3089 "#endif\n"
3090 "\n"
3091 "       gl_FragColor = float4(color);\n"
3092 "}\n"
3093 "#endif // FRAGMENT_SHADER\n"
3094 "\n"
3095 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3096 "#endif // !MODE_DEFERREDGEOMETRY\n"
3097 "#endif // !MODE_WATER\n"
3098 "#endif // !MODE_REFRACTION\n"
3099 "#endif // !MODE_BLOOMBLUR\n"
3100 "#endif // !MODE_GENERIC\n"
3101 "#endif // !MODE_POSTPROCESS\n"
3102 "#endif // !MODE_SHOWDEPTH\n"
3103 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3104 ;
3105
3106 //=======================================================================================================================================================
3107
3108 typedef struct shaderpermutationinfo_s
3109 {
3110         const char *pretext;
3111         const char *name;
3112 }
3113 shaderpermutationinfo_t;
3114
3115 typedef struct shadermodeinfo_s
3116 {
3117         const char *vertexfilename;
3118         const char *geometryfilename;
3119         const char *fragmentfilename;
3120         const char *pretext;
3121         const char *name;
3122 }
3123 shadermodeinfo_t;
3124
3125 typedef enum shaderpermutation_e
3126 {
3127         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3128         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3129         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3130         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3131         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3132         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3133         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3134         SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
3135         SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
3136         SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
3137         SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
3138         SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
3139         SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
3140         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3141         SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3142         SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3143         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3144         SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
3145         SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
3146         SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
3147         SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
3148         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3149         SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
3150         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3151         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3152         SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3153         SHADERPERMUTATION_LIMIT = 1<<26, ///< size of permutations array
3154         SHADERPERMUTATION_COUNT = 26 ///< size of shaderpermutationinfo array
3155 }
3156 shaderpermutation_t;
3157
3158 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3159 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3160 {
3161         {"#define USEDIFFUSE\n", " diffuse"},
3162         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3163         {"#define USEVIEWTINT\n", " viewtint"},
3164         {"#define USECOLORMAPPING\n", " colormapping"},
3165         {"#define USESATURATION\n", " saturation"},
3166         {"#define USEFOGINSIDE\n", " foginside"},
3167         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3168         {"#define USEGAMMARAMPS\n", " gammaramps"},
3169         {"#define USECUBEFILTER\n", " cubefilter"},
3170         {"#define USEGLOW\n", " glow"},
3171         {"#define USEBLOOM\n", " bloom"},
3172         {"#define USESPECULAR\n", " specular"},
3173         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3174         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3175         {"#define USEREFLECTION\n", " reflection"},
3176         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3177         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3178         {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3179         {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3180         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3181         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3182         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3183         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3184         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3185         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3186         {"#define USEALPHAKILL\n", " alphakill"},
3187 };
3188
3189 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3190 typedef enum shadermode_e
3191 {
3192         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3193         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3194         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3195         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3196         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3197         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3198         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3199         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3200         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3201         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3202         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3203         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3204         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3205         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3206         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3207         SHADERMODE_COUNT
3208 }
3209 shadermode_t;
3210
3211 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3212 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3213 {
3214         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3215         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3216         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3217         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3218         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3219         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3220         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3221         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3222         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3223         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3224         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3225         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3226         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3227         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3228         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3229 };
3230
3231 #ifdef SUPPORTCG
3232 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3233 {
3234         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3235         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3236         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3237         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3238         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3239         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3240         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3241         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3242         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3243         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3244         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3245         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3246         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3247         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3248         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3249 };
3250 #endif
3251
3252 struct r_glsl_permutation_s;
3253 typedef struct r_glsl_permutation_s
3254 {
3255         /// hash lookup data
3256         struct r_glsl_permutation_s *hashnext;
3257         unsigned int mode;
3258         unsigned int permutation;
3259
3260         /// indicates if we have tried compiling this permutation already
3261         qboolean compiled;
3262         /// 0 if compilation failed
3263         int program;
3264         /// locations of detected uniforms in program object, or -1 if not found
3265         int loc_Texture_First;
3266         int loc_Texture_Second;
3267         int loc_Texture_GammaRamps;
3268         int loc_Texture_Normal;
3269         int loc_Texture_Color;
3270         int loc_Texture_Gloss;
3271         int loc_Texture_Glow;
3272         int loc_Texture_SecondaryNormal;
3273         int loc_Texture_SecondaryColor;
3274         int loc_Texture_SecondaryGloss;
3275         int loc_Texture_SecondaryGlow;
3276         int loc_Texture_Pants;
3277         int loc_Texture_Shirt;
3278         int loc_Texture_FogMask;
3279         int loc_Texture_Lightmap;
3280         int loc_Texture_Deluxemap;
3281         int loc_Texture_Attenuation;
3282         int loc_Texture_Cube;
3283         int loc_Texture_Refraction;
3284         int loc_Texture_Reflection;
3285         int loc_Texture_ShadowMapRect;
3286         int loc_Texture_ShadowMapCube;
3287         int loc_Texture_ShadowMap2D;
3288         int loc_Texture_CubeProjection;
3289         int loc_Texture_ScreenDepth;
3290         int loc_Texture_ScreenNormalMap;
3291         int loc_Texture_ScreenDiffuse;
3292         int loc_Texture_ScreenSpecular;
3293         int loc_Alpha;
3294         int loc_BloomBlur_Parameters;
3295         int loc_ClientTime;
3296         int loc_Color_Ambient;
3297         int loc_Color_Diffuse;
3298         int loc_Color_Specular;
3299         int loc_Color_Glow;
3300         int loc_Color_Pants;
3301         int loc_Color_Shirt;
3302         int loc_DeferredColor_Ambient;
3303         int loc_DeferredColor_Diffuse;
3304         int loc_DeferredColor_Specular;
3305         int loc_DeferredMod_Diffuse;
3306         int loc_DeferredMod_Specular;
3307         int loc_DistortScaleRefractReflect;
3308         int loc_EyePosition;
3309         int loc_FogColor;
3310         int loc_FogHeightFade;
3311         int loc_FogPlane;
3312         int loc_FogPlaneViewDist;
3313         int loc_FogRangeRecip;
3314         int loc_LightColor;
3315         int loc_LightDir;
3316         int loc_LightPosition;
3317         int loc_OffsetMapping_Scale;
3318         int loc_PixelSize;
3319         int loc_ReflectColor;
3320         int loc_ReflectFactor;
3321         int loc_ReflectOffset;
3322         int loc_RefractColor;
3323         int loc_Saturation;
3324         int loc_ScreenCenterRefractReflect;
3325         int loc_ScreenScaleRefractReflect;
3326         int loc_ScreenToDepth;
3327         int loc_ShadowMap_Parameters;
3328         int loc_ShadowMap_TextureScale;
3329         int loc_SpecularPower;
3330         int loc_UserVec1;
3331         int loc_UserVec2;
3332         int loc_UserVec3;
3333         int loc_UserVec4;
3334         int loc_ViewTintColor;
3335         int loc_ViewToLight;
3336         int loc_ModelToLight;
3337         int loc_TexMatrix;
3338         int loc_BackgroundTexMatrix;
3339         int loc_ModelViewProjectionMatrix;
3340         int loc_ModelViewMatrix;
3341 }
3342 r_glsl_permutation_t;
3343
3344 #define SHADERPERMUTATION_HASHSIZE 256
3345
3346 /// information about each possible shader permutation
3347 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3348 /// currently selected permutation
3349 r_glsl_permutation_t *r_glsl_permutation;
3350 /// storage for permutations linked in the hash table
3351 memexpandablearray_t r_glsl_permutationarray;
3352
3353 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3354 {
3355         //unsigned int hashdepth = 0;
3356         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3357         r_glsl_permutation_t *p;
3358         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3359         {
3360                 if (p->mode == mode && p->permutation == permutation)
3361                 {
3362                         //if (hashdepth > 10)
3363                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3364                         return p;
3365                 }
3366                 //hashdepth++;
3367         }
3368         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3369         p->mode = mode;
3370         p->permutation = permutation;
3371         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3372         r_glsl_permutationhash[mode][hashindex] = p;
3373         //if (hashdepth > 10)
3374         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3375         return p;
3376 }
3377
3378 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3379 {
3380         char *shaderstring;
3381         if (!filename || !filename[0])
3382                 return NULL;
3383         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3384         if (shaderstring)
3385         {
3386                 if (printfromdisknotice)
3387                         Con_DPrintf("from disk %s... ", filename);
3388                 return shaderstring;
3389         }
3390         else if (!strcmp(filename, "glsl/default.glsl"))
3391         {
3392                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
3393                 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
3394         }
3395         return shaderstring;
3396 }
3397
3398 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3399 {
3400         int i;
3401         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3402         int vertstrings_count = 0;
3403         int geomstrings_count = 0;
3404         int fragstrings_count = 0;
3405         char *vertexstring, *geometrystring, *fragmentstring;
3406         const char *vertstrings_list[32+3];
3407         const char *geomstrings_list[32+3];
3408         const char *fragstrings_list[32+3];
3409         char permutationname[256];
3410
3411         if (p->compiled)
3412                 return;
3413         p->compiled = true;
3414         p->program = 0;
3415
3416         permutationname[0] = 0;
3417         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3418         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3419         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3420
3421         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3422
3423         // the first pretext is which type of shader to compile as
3424         // (later these will all be bound together as a program object)
3425         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3426         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3427         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3428
3429         // the second pretext is the mode (for example a light source)
3430         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3431         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3432         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3433         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3434
3435         // now add all the permutation pretexts
3436         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3437         {
3438                 if (permutation & (1<<i))
3439                 {
3440                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3441                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3442                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3443                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3444                 }
3445                 else
3446                 {
3447                         // keep line numbers correct
3448                         vertstrings_list[vertstrings_count++] = "\n";
3449                         geomstrings_list[geomstrings_count++] = "\n";
3450                         fragstrings_list[fragstrings_count++] = "\n";
3451                 }
3452         }
3453
3454         // now append the shader text itself
3455         vertstrings_list[vertstrings_count++] = vertexstring;
3456         geomstrings_list[geomstrings_count++] = geometrystring;
3457         fragstrings_list[fragstrings_count++] = fragmentstring;
3458
3459         // if any sources were NULL, clear the respective list
3460         if (!vertexstring)
3461                 vertstrings_count = 0;
3462         if (!geometrystring)
3463                 geomstrings_count = 0;
3464         if (!fragmentstring)
3465                 fragstrings_count = 0;
3466
3467         // compile the shader program
3468         if (vertstrings_count + geomstrings_count + fragstrings_count)
3469                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3470         if (p->program)
3471         {
3472                 CHECKGLERROR
3473                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3474                 // look up all the uniform variable names we care about, so we don't
3475                 // have to look them up every time we set them
3476
3477                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3478                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3479                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3480                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3481                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3482                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3483                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3484                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3485                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3486                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3487                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3488                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3489                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3490                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3491                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3492                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3493                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3494                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3495                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3496                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3497                 p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3498                 p->loc_Texture_ShadowMapCube      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3499                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3500                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3501                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3502                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3503                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3504                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3505                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3506                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3507                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3508                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3509                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3510                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3511                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3512                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3513                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3514                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3515                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3516                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3517                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3518                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3519                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3520                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3521                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3522                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3523                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3524                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3525                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3526                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3527                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3528                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3529                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3530                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3531                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3532                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3533                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3534                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3535                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3536                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3537                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3538                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3539                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3540                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3541                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3542                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3543                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3544                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3545                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3546                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3547                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3548                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3549                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3550                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3551                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3552                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3553                 // initialize the samplers to refer to the texture units we use
3554                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3555                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3556                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3557                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3558                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3559                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3560                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3561                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3562                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3563                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3564                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3565                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3566                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3567                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3568                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3569                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3570                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3571                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3572                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3573                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3574                 if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , GL20TU_SHADOWMAPRECT);
3575                 if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
3576                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
3577                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3578                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3579                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3580                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3581                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3582                 CHECKGLERROR
3583                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3584         }
3585         else
3586                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3587
3588         // free the strings
3589         if (vertexstring)
3590                 Mem_Free(vertexstring);
3591         if (geometrystring)
3592                 Mem_Free(geometrystring);
3593         if (fragmentstring)
3594                 Mem_Free(fragmentstring);
3595 }
3596
3597 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3598 {
3599         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3600         if (r_glsl_permutation != perm)
3601         {
3602                 r_glsl_permutation = perm;
3603                 if (!r_glsl_permutation->program)
3604                 {
3605                         if (!r_glsl_permutation->compiled)
3606                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3607                         if (!r_glsl_permutation->program)
3608                         {
3609                                 // remove features until we find a valid permutation
3610                                 int i;
3611                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3612                                 {
3613                                         // reduce i more quickly whenever it would not remove any bits
3614                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3615                                         if (!(permutation & j))
3616                                                 continue;
3617                                         permutation -= j;
3618                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3619                                         if (!r_glsl_permutation->compiled)
3620                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3621                                         if (r_glsl_permutation->program)
3622                                                 break;
3623                                 }
3624                                 if (i >= SHADERPERMUTATION_COUNT)
3625                                 {
3626                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3627                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3628                                         qglUseProgramObjectARB(0);CHECKGLERROR
3629                                         return; // no bit left to clear, entire mode is broken
3630                                 }
3631                         }
3632                 }
3633                 CHECKGLERROR
3634                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3635         }
3636         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3637         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3638 }
3639
3640 #ifdef SUPPORTCG
3641 #include <Cg/cgGL.h>
3642 struct r_cg_permutation_s;
3643 typedef struct r_cg_permutation_s
3644 {
3645         /// hash lookup data
3646         struct r_cg_permutation_s *hashnext;
3647         unsigned int mode;
3648         unsigned int permutation;
3649
3650         /// indicates if we have tried compiling this permutation already
3651         qboolean compiled;
3652         /// 0 if compilation failed
3653         CGprogram vprogram;
3654         CGprogram fprogram;
3655         /// locations of detected parameters in programs, or NULL if not found
3656         CGparameter vp_EyePosition;
3657         CGparameter vp_FogPlane;
3658         CGparameter vp_LightDir;
3659         CGparameter vp_LightPosition;
3660         CGparameter vp_ModelToLight;
3661         CGparameter vp_TexMatrix;
3662         CGparameter vp_BackgroundTexMatrix;
3663         CGparameter vp_ModelViewProjectionMatrix;
3664         CGparameter vp_ModelViewMatrix;
3665
3666         CGparameter fp_Texture_First;
3667         CGparameter fp_Texture_Second;
3668         CGparameter fp_Texture_GammaRamps;
3669         CGparameter fp_Texture_Normal;
3670         CGparameter fp_Texture_Color;
3671         CGparameter fp_Texture_Gloss;
3672         CGparameter fp_Texture_Glow;
3673         CGparameter fp_Texture_SecondaryNormal;
3674         CGparameter fp_Texture_SecondaryColor;
3675         CGparameter fp_Texture_SecondaryGloss;
3676         CGparameter fp_Texture_SecondaryGlow;
3677         CGparameter fp_Texture_Pants;
3678         CGparameter fp_Texture_Shirt;
3679         CGparameter fp_Texture_FogMask;
3680         CGparameter fp_Texture_Lightmap;
3681         CGparameter fp_Texture_Deluxemap;
3682         CGparameter fp_Texture_Attenuation;
3683         CGparameter fp_Texture_Cube;
3684         CGparameter fp_Texture_Refraction;
3685         CGparameter fp_Texture_Reflection;
3686         CGparameter fp_Texture_ShadowMapRect;
3687         CGparameter fp_Texture_ShadowMapCube;
3688         CGparameter fp_Texture_ShadowMap2D;
3689         CGparameter fp_Texture_CubeProjection;
3690         CGparameter fp_Texture_ScreenDepth;
3691         CGparameter fp_Texture_ScreenNormalMap;
3692         CGparameter fp_Texture_ScreenDiffuse;
3693         CGparameter fp_Texture_ScreenSpecular;
3694         CGparameter fp_Alpha;
3695         CGparameter fp_BloomBlur_Parameters;
3696         CGparameter fp_ClientTime;
3697         CGparameter fp_Color_Ambient;
3698         CGparameter fp_Color_Diffuse;
3699         CGparameter fp_Color_Specular;
3700         CGparameter fp_Color_Glow;
3701         CGparameter fp_Color_Pants;
3702         CGparameter fp_Color_Shirt;
3703         CGparameter fp_DeferredColor_Ambient;
3704         CGparameter fp_DeferredColor_Diffuse;
3705         CGparameter fp_DeferredColor_Specular;
3706         CGparameter fp_DeferredMod_Diffuse;
3707         CGparameter fp_DeferredMod_Specular;
3708         CGparameter fp_DistortScaleRefractReflect;
3709         CGparameter fp_EyePosition;
3710         CGparameter fp_FogColor;
3711         CGparameter fp_FogHeightFade;
3712         CGparameter fp_FogPlane;
3713         CGparameter fp_FogPlaneViewDist;
3714         CGparameter fp_FogRangeRecip;
3715         CGparameter fp_LightColor;
3716         CGparameter fp_LightDir;
3717         CGparameter fp_LightPosition;
3718         CGparameter fp_OffsetMapping_Scale;
3719         CGparameter fp_PixelSize;
3720         CGparameter fp_ReflectColor;
3721         CGparameter fp_ReflectFactor;
3722         CGparameter fp_ReflectOffset;
3723         CGparameter fp_RefractColor;
3724         CGparameter fp_Saturation;
3725         CGparameter fp_ScreenCenterRefractReflect;
3726         CGparameter fp_ScreenScaleRefractReflect;
3727         CGparameter fp_ScreenToDepth;
3728         CGparameter fp_ShadowMap_Parameters;
3729         CGparameter fp_ShadowMap_TextureScale;
3730         CGparameter fp_SpecularPower;
3731         CGparameter fp_UserVec1;
3732         CGparameter fp_UserVec2;
3733         CGparameter fp_UserVec3;
3734         CGparameter fp_UserVec4;
3735         CGparameter fp_ViewTintColor;
3736         CGparameter fp_ViewToLight;
3737 }
3738 r_cg_permutation_t;
3739
3740 /// information about each possible shader permutation
3741 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3742 /// currently selected permutation
3743 r_cg_permutation_t *r_cg_permutation;
3744 /// storage for permutations linked in the hash table
3745 memexpandablearray_t r_cg_permutationarray;
3746
3747 #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));}}
3748
3749 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3750 {
3751         //unsigned int hashdepth = 0;
3752         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3753         r_cg_permutation_t *p;
3754         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3755         {
3756                 if (p->mode == mode && p->permutation == permutation)
3757                 {
3758                         //if (hashdepth > 10)
3759                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3760                         return p;
3761                 }
3762                 //hashdepth++;
3763         }
3764         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3765         p->mode = mode;
3766         p->permutation = permutation;
3767         p->hashnext = r_cg_permutationhash[mode][hashindex];
3768         r_cg_permutationhash[mode][hashindex] = p;
3769         //if (hashdepth > 10)
3770         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3771         return p;
3772 }
3773
3774 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3775 {
3776         char *shaderstring;
3777         if (!filename || !filename[0])
3778                 return NULL;
3779         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3780         if (shaderstring)
3781         {
3782                 if (printfromdisknotice)
3783                         Con_DPrintf("from disk %s... ", filename);
3784                 return shaderstring;
3785         }
3786         else if (!strcmp(filename, "cg/default.cg"))
3787         {
3788                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtincgshaderstring) + 1);
3789                 memcpy(shaderstring, builtincgshaderstring, strlen(builtincgshaderstring) + 1);
3790         }
3791         return shaderstring;
3792 }
3793
3794 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
3795 {
3796         int i;
3797         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
3798         int vertstrings_count = 0, vertstring_length = 0;
3799         int geomstrings_count = 0, geomstring_length = 0;
3800         int fragstrings_count = 0, fragstring_length = 0;
3801         char *t;
3802         char *vertexstring, *geometrystring, *fragmentstring;
3803         char *vertstring, *geomstring, *fragstring;
3804         const char *vertstrings_list[32+3];
3805         const char *geomstrings_list[32+3];
3806         const char *fragstrings_list[32+3];
3807         char permutationname[256];
3808         CGprofile vertexProfile;
3809         CGprofile fragmentProfile;
3810
3811         if (p->compiled)
3812                 return;
3813         p->compiled = true;
3814         p->vprogram = NULL;
3815         p->fprogram = NULL;
3816
3817         permutationname[0] = 0;
3818         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
3819         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
3820         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
3821
3822         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3823
3824         // the first pretext is which type of shader to compile as
3825         // (later these will all be bound together as a program object)
3826         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3827         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3828         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3829
3830         // the second pretext is the mode (for example a light source)
3831         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3832         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3833         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3834         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3835
3836         // now add all the permutation pretexts
3837         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3838         {
3839                 if (permutation & (1<<i))
3840                 {
3841                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3842                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3843                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3844                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3845                 }
3846                 else
3847                 {
3848                         // keep line numbers correct
3849                         vertstrings_list[vertstrings_count++] = "\n";
3850                         geomstrings_list[geomstrings_count++] = "\n";
3851                         fragstrings_list[fragstrings_count++] = "\n";
3852                 }
3853         }
3854
3855         // now append the shader text itself
3856         vertstrings_list[vertstrings_count++] = vertexstring;
3857         geomstrings_list[geomstrings_count++] = geometrystring;
3858         fragstrings_list[fragstrings_count++] = fragmentstring;
3859
3860         // if any sources were NULL, clear the respective list
3861         if (!vertexstring)
3862                 vertstrings_count = 0;
3863         if (!geometrystring)
3864                 geomstrings_count = 0;
3865         if (!fragmentstring)
3866                 fragstrings_count = 0;
3867
3868         vertstring_length = 0;
3869         for (i = 0;i < vertstrings_count;i++)
3870                 vertstring_length += strlen(vertstrings_list[i]);
3871         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
3872         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
3873                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
3874
3875         geomstring_length = 0;
3876         for (i = 0;i < geomstrings_count;i++)
3877                 geomstring_length += strlen(geomstrings_list[i]);
3878         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
3879         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
3880                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
3881
3882         fragstring_length = 0;
3883         for (i = 0;i < fragstrings_count;i++)
3884                 fragstring_length += strlen(fragstrings_list[i]);
3885         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
3886         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
3887                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
3888
3889         CHECKGLERROR
3890         CHECKCGERROR
3891         //vertexProfile = CG_PROFILE_ARBVP1;
3892         //fragmentProfile = CG_PROFILE_ARBFP1;
3893         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
3894         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
3895         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
3896         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
3897         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
3898         CHECKGLERROR
3899
3900         // compile the vertex program
3901         if (vertstring[0] && (p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL)))
3902         {
3903                 CHECKCGERROR
3904                 cgCompileProgram(p->vprogram);CHECKCGERROR
3905                 if (!cgIsProgramCompiled(p->vprogram))
3906                 {
3907                         CHECKCGERROR
3908                         cgDestroyProgram(p->vprogram);CHECKCGERROR
3909                         p->vprogram = 0;
3910                 }
3911                 else
3912                 {
3913                         cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
3914                         cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
3915                         // look up all the uniform variable names we care about, so we don't
3916                         // have to look them up every time we set them
3917                         CHECKCGERROR
3918                         p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
3919                         p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
3920                         p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
3921                         p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
3922                         p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
3923                         p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
3924                         p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
3925                         p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
3926                         p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
3927                         CHECKCGERROR
3928                 }
3929         }
3930
3931         // compile the fragment program
3932         if (fragstring[0] && (p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL)))
3933         {
3934                 cgCompileProgram(p->fprogram);CHECKCGERROR
3935                 if (!cgIsProgramCompiled(p->fprogram))
3936                 {
3937                         CHECKCGERROR
3938                         cgDestroyProgram(p->fprogram);CHECKCGERROR
3939                         p->fprogram = 0;
3940                 }
3941                 else
3942                 {
3943                         cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
3944                         cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
3945                         CHECKCGERROR
3946                         p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
3947                         p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
3948                         p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
3949                         p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
3950                         p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
3951                         p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
3952                         p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
3953                         p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
3954                         p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
3955                         p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
3956                         p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
3957                         p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
3958                         p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
3959                         p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
3960                         p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
3961                         p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
3962                         p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
3963                         p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
3964                         p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
3965                         p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
3966                         p->fp_Texture_ShadowMapRect      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
3967                         p->fp_Texture_ShadowMapCube      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
3968                         p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
3969                         p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
3970                         p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
3971                         p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
3972                         p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
3973                         p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
3974                         p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
3975                         p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
3976                         p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
3977                         p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
3978                         p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
3979                         p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
3980                         p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
3981                         p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
3982                         p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
3983                         p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
3984                         p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
3985                         p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
3986                         p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
3987                         p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
3988                         p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
3989                         p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
3990                         p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
3991                         p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
3992                         p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
3993                         p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
3994                         p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
3995                         p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
3996                         p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
3997                         p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
3998                         p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
3999                         p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4000                         p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4001                         p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4002                         p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4003                         p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4004                         p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4005                         p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4006                         p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4007                         p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4008                         p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4009                         p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4010                         p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4011                         p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4012                         p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4013                         p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4014                         p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4015                         p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4016                         p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4017                         CHECKCGERROR
4018                 }
4019         }
4020
4021         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4022                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4023         else
4024                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4025
4026         // free the strings
4027         if (vertstring)
4028                 Mem_Free(vertstring);
4029         if (geomstring)
4030                 Mem_Free(geomstring);
4031         if (fragstring)
4032                 Mem_Free(fragstring);
4033         if (vertexstring)
4034                 Mem_Free(vertexstring);
4035         if (geometrystring)
4036                 Mem_Free(geometrystring);
4037         if (fragmentstring)
4038                 Mem_Free(fragmentstring);
4039 }
4040
4041 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4042 {
4043         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4044         CHECKGLERROR
4045         CHECKCGERROR
4046         if (r_cg_permutation != perm)
4047         {
4048                 r_cg_permutation = perm;
4049                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4050                 {
4051                         if (!r_cg_permutation->compiled)
4052                                 R_CG_CompilePermutation(perm, mode, permutation);
4053                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4054                         {
4055                                 // remove features until we find a valid permutation
4056                                 int i;
4057                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4058                                 {
4059                                         // reduce i more quickly whenever it would not remove any bits
4060                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4061                                         if (!(permutation & j))
4062                                                 continue;
4063                                         permutation -= j;
4064                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4065                                         if (!r_cg_permutation->compiled)
4066                                                 R_CG_CompilePermutation(perm, mode, permutation);
4067                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4068                                                 break;
4069                                 }
4070                                 if (i >= SHADERPERMUTATION_COUNT)
4071                                 {
4072                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4073                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4074                                         return; // no bit left to clear, entire mode is broken
4075                                 }
4076                         }
4077                 }
4078                 CHECKGLERROR
4079                 CHECKCGERROR
4080                 if (r_cg_permutation->vprogram)
4081                 {
4082                         //cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4083                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4084                         //cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4085                 }
4086                 else
4087                 {
4088                         //cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4089                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4090                 }
4091                 if (r_cg_permutation->fprogram)
4092                 {
4093                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4094                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4095                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4096                 }
4097                 else
4098                 {
4099                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4100                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4101                 }
4102         }
4103         CHECKCGERROR
4104         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4105         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4106 }
4107
4108 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4109 {
4110         cgGLSetTextureParameter(param, R_GetTexture(tex));
4111         cgGLEnableTextureParameter(param);
4112 }
4113 #endif
4114
4115 void R_GLSL_Restart_f(void)
4116 {
4117         unsigned int i, limit;
4118         switch(vid.renderpath)
4119         {
4120         case RENDERPATH_GL20:
4121                 {
4122                         r_glsl_permutation_t *p;
4123                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4124                         for (i = 0;i < limit;i++)
4125                         {
4126                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4127                                 {
4128                                         GL_Backend_FreeProgram(p->program);
4129                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4130                                 }
4131                         }
4132                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4133                 }
4134                 break;
4135         case RENDERPATH_CGGL:
4136 #ifdef SUPPORTCG
4137                 {
4138                         r_cg_permutation_t *p;
4139                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4140                         for (i = 0;i < limit;i++)
4141                         {
4142                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4143                                 {
4144                                         if (p->vprogram)
4145                                                 cgDestroyProgram(p->vprogram);
4146                                         if (p->fprogram)
4147                                                 cgDestroyProgram(p->fprogram);
4148                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4149                                 }
4150                         }
4151                 }
4152                 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4153                 break;
4154 #endif
4155         case RENDERPATH_GL13:
4156         case RENDERPATH_GL11:
4157                 break;
4158         }
4159 }
4160
4161 void R_GLSL_DumpShader_f(void)
4162 {
4163         int i;
4164         qfile_t *file;
4165
4166         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4167         if (file)
4168         {
4169                 FS_Print(file, "/* The engine may define the following macros:\n");
4170                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4171                 for (i = 0;i < SHADERMODE_COUNT;i++)
4172                         FS_Print(file, glslshadermodeinfo[i].pretext);
4173                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4174                         FS_Print(file, shaderpermutationinfo[i].pretext);
4175                 FS_Print(file, "*/\n");
4176                 FS_Print(file, builtinshaderstring);
4177                 FS_Close(file);
4178                 Con_Printf("glsl/default.glsl written\n");
4179         }
4180         else
4181                 Con_Printf("failed to write to glsl/default.glsl\n");
4182
4183 #ifdef SUPPORTCG
4184         file = FS_OpenRealFile("cg/default.cg", "w", false);
4185         if (file)
4186         {
4187                 FS_Print(file, "/* The engine may define the following macros:\n");
4188                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4189                 for (i = 0;i < SHADERMODE_COUNT;i++)
4190                         FS_Print(file, cgshadermodeinfo[i].pretext);
4191                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4192                         FS_Print(file, shaderpermutationinfo[i].pretext);
4193                 FS_Print(file, "*/\n");
4194                 FS_Print(file, builtincgshaderstring);
4195                 FS_Close(file);
4196                 Con_Printf("cg/default.cg written\n");
4197         }
4198         else
4199                 Con_Printf("failed to write to cg/default.cg\n");
4200 #endif
4201 }
4202
4203 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4204 {
4205         if (!second)
4206                 texturemode = GL_MODULATE;
4207         switch (vid.renderpath)
4208         {
4209         case RENDERPATH_GL20:
4210                 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))));
4211                 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
4212                 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, second);
4213                 break;
4214         case RENDERPATH_CGGL:
4215 #ifdef SUPPORTCG
4216                 CHECKCGERROR
4217                 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))));
4218                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4219                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4220 #endif
4221                 break;
4222         case RENDERPATH_GL13:
4223                 R_Mesh_TexBind(0, first );
4224                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4225                 R_Mesh_TexBind(1, second);
4226                 if (second)
4227                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4228                 break;
4229         case RENDERPATH_GL11:
4230                 R_Mesh_TexBind(0, first );
4231                 break;
4232         }
4233 }
4234
4235 void R_SetupShader_DepthOrShadow(void)
4236 {
4237         switch (vid.renderpath)
4238         {
4239         case RENDERPATH_GL20:
4240                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4241                 break;
4242         case RENDERPATH_CGGL:
4243 #ifdef SUPPORTCG
4244                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4245 #endif
4246                 break;
4247         case RENDERPATH_GL13:
4248                 R_Mesh_TexBind(0, 0);
4249                 R_Mesh_TexBind(1, 0);
4250                 break;
4251         case RENDERPATH_GL11:
4252                 R_Mesh_TexBind(0, 0);
4253                 break;
4254         }
4255 }
4256
4257 void R_SetupShader_ShowDepth(void)
4258 {
4259         switch (vid.renderpath)
4260         {
4261         case RENDERPATH_GL20:
4262                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4263                 break;
4264         case RENDERPATH_CGGL:
4265 #ifdef SUPPORTCG
4266                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4267 #endif
4268                 break;
4269         case RENDERPATH_GL13:
4270                 break;
4271         case RENDERPATH_GL11:
4272                 break;
4273         }
4274 }
4275
4276 extern qboolean r_shadow_usingdeferredprepass;
4277 extern cvar_t r_shadow_deferred_8bitrange;
4278 extern rtexture_t *r_shadow_attenuationgradienttexture;
4279 extern rtexture_t *r_shadow_attenuation2dtexture;
4280 extern rtexture_t *r_shadow_attenuation3dtexture;
4281 extern qboolean r_shadow_usingshadowmaprect;
4282 extern qboolean r_shadow_usingshadowmapcube;
4283 extern qboolean r_shadow_usingshadowmap2d;
4284 extern float r_shadow_shadowmap_texturescale[2];
4285 extern float r_shadow_shadowmap_parameters[4];
4286 extern qboolean r_shadow_shadowmapvsdct;
4287 extern qboolean r_shadow_shadowmapsampler;
4288 extern int r_shadow_shadowmappcf;
4289 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4290 extern rtexture_t *r_shadow_shadowmap2dtexture;
4291 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4292 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4293 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4294 extern int r_shadow_prepass_width;
4295 extern int r_shadow_prepass_height;
4296 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4297 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4298 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4299 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4300 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
4301 {
4302         // select a permutation of the lighting shader appropriate to this
4303         // combination of texture, entity, light source, and fogging, only use the
4304         // minimum features necessary to avoid wasting rendering time in the
4305         // fragment shader on features that are not being used
4306         unsigned int permutation = 0;
4307         unsigned int mode = 0;
4308         float m16f[16];
4309         if (rsurfacepass == RSURFPASS_BACKGROUND)
4310         {
4311                 // distorted background
4312                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4313                         mode = SHADERMODE_WATER;
4314                 else
4315                         mode = SHADERMODE_REFRACTION;
4316                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4317                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4318                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4319                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4320                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4321                 R_Mesh_ColorPointer(NULL, 0, 0);
4322                 GL_AlphaTest(false);
4323                 GL_BlendFunc(GL_ONE, GL_ZERO);
4324         }
4325         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4326         {
4327                 if (r_glsl_offsetmapping.integer)
4328                 {
4329                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4330                         if (r_glsl_offsetmapping_reliefmapping.integer)
4331                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4332                 }
4333                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4334                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4335                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4336                         permutation |= SHADERPERMUTATION_ALPHAKILL;
4337                 // normalmap (deferred prepass), may use alpha test on diffuse
4338                 mode = SHADERMODE_DEFERREDGEOMETRY;
4339                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4340                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4341                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4342                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4343                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4344                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4345                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4346                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4347                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4348                 else
4349                         R_Mesh_ColorPointer(NULL, 0, 0);
4350                 GL_AlphaTest(false);
4351                 GL_BlendFunc(GL_ONE, GL_ZERO);
4352         }
4353         else if (rsurfacepass == RSURFPASS_RTLIGHT)
4354         {
4355                 if (r_glsl_offsetmapping.integer)
4356                 {
4357                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4358                         if (r_glsl_offsetmapping_reliefmapping.integer)
4359                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4360                 }
4361                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4362                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4363                 // light source
4364                 mode = SHADERMODE_LIGHTSOURCE;
4365                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4366                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4367                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4368                         permutation |= SHADERPERMUTATION_CUBEFILTER;
4369                 if (diffusescale > 0)
4370                         permutation |= SHADERPERMUTATION_DIFFUSE;
4371                 if (specularscale > 0)
4372                 {
4373                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4374                         if (r_shadow_glossexact.integer)
4375                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4376                 }
4377                 if (r_refdef.fogenabled)
4378                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4379                 if (rsurface.texture->colormapping)
4380                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4381                 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4382                 {
4383                         if (r_shadow_usingshadowmaprect)
4384                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4385                         if (r_shadow_usingshadowmap2d)
4386                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4387                         if (r_shadow_usingshadowmapcube)
4388                                 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4389                         else if(r_shadow_shadowmapvsdct)
4390                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4391
4392                         if (r_shadow_shadowmapsampler)
4393                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4394                         if (r_shadow_shadowmappcf > 1)
4395                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4396                         else if (r_shadow_shadowmappcf)
4397                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4398                 }
4399                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4400                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4401                 {
4402                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4403                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4404                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4405                 }
4406                 else
4407                 {
4408                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4409                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4410                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4411                 }
4412                 //R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4413                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4414                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4415                 else
4416                         R_Mesh_ColorPointer(NULL, 0, 0);
4417                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4418                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4419         }
4420         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4421         {
4422                 if (r_glsl_offsetmapping.integer)
4423                 {
4424                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4425                         if (r_glsl_offsetmapping_reliefmapping.integer)
4426                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4427                 }
4428                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4429                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4430                 // unshaded geometry (fullbright or ambient model lighting)
4431                 mode = SHADERMODE_FLATCOLOR;
4432                 ambientscale = diffusescale = specularscale = 0;
4433                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4434                         permutation |= SHADERPERMUTATION_GLOW;
4435                 if (r_refdef.fogenabled)
4436                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4437                 if (rsurface.texture->colormapping)
4438                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4439                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4440                         permutation |= SHADERPERMUTATION_REFLECTION;
4441                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4442                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4443                 {
4444                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4445                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4446                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4447                 }
4448                 else
4449                 {
4450                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4451                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4452                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4453                 }
4454                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4455                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4456                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4457                 else
4458                         R_Mesh_ColorPointer(NULL, 0, 0);
4459                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4460                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4461         }
4462         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4463         {
4464                 if (r_glsl_offsetmapping.integer)
4465                 {
4466                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4467                         if (r_glsl_offsetmapping_reliefmapping.integer)
4468                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4469                 }
4470                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4471                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4472                 // directional model lighting
4473                 mode = SHADERMODE_LIGHTDIRECTION;
4474                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4475                         permutation |= SHADERPERMUTATION_GLOW;
4476                 permutation |= SHADERPERMUTATION_DIFFUSE;
4477                 if (specularscale > 0)
4478                 {
4479                         permutation |= SHADERPERMUTATION_SPECULAR;
4480                         if (r_shadow_glossexact.integer)
4481                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4482                 }
4483                 if (r_refdef.fogenabled)
4484                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4485                 if (rsurface.texture->colormapping)
4486                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4487                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4488                         permutation |= SHADERPERMUTATION_REFLECTION;
4489                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4490                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4491                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4492                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4493                 {
4494                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4495                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4496                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4497                 }
4498                 else
4499                 {
4500                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4501                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4502                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4503                 }
4504                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4505                 R_Mesh_ColorPointer(NULL, 0, 0);
4506                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4507                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4508         }
4509         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
4510         {
4511                 if (r_glsl_offsetmapping.integer)
4512                 {
4513                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4514                         if (r_glsl_offsetmapping_reliefmapping.integer)
4515                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4516                 }
4517                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4518                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4519                 // ambient model lighting
4520                 mode = SHADERMODE_LIGHTDIRECTION;
4521                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4522                         permutation |= SHADERPERMUTATION_GLOW;
4523                 if (r_refdef.fogenabled)
4524                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4525                 if (rsurface.texture->colormapping)
4526                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4527                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4528                         permutation |= SHADERPERMUTATION_REFLECTION;
4529                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4530                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4531                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4532                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4533                 {
4534                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4535                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4536                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4537                 }
4538                 else
4539                 {
4540                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4541                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4542                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4543                 }
4544                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4545                 R_Mesh_ColorPointer(NULL, 0, 0);
4546                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4547                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4548         }
4549         else
4550         {
4551                 if (r_glsl_offsetmapping.integer)
4552                 {
4553                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4554                         if (r_glsl_offsetmapping_reliefmapping.integer)
4555                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4556                 }
4557                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4558                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4559                 // lightmapped wall
4560                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4561                         permutation |= SHADERPERMUTATION_GLOW;
4562                 if (r_refdef.fogenabled)
4563                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4564                 if (rsurface.texture->colormapping)
4565                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4566                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4567                         permutation |= SHADERPERMUTATION_REFLECTION;
4568                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4569                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4570                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
4571                 {
4572                         // deluxemapping (light direction texture)
4573                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
4574                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
4575                         else
4576                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4577                         permutation |= SHADERPERMUTATION_DIFFUSE;
4578                         if (specularscale > 0)
4579                         {
4580                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4581                                 if (r_shadow_glossexact.integer)
4582                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4583                         }
4584                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4585                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4586                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4587                         else
4588                                 R_Mesh_ColorPointer(NULL, 0, 0);
4589                 }
4590                 else if (r_glsl_deluxemapping.integer >= 2)
4591                 {
4592                         // fake deluxemapping (uniform light direction in tangentspace)
4593                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4594                         permutation |= SHADERPERMUTATION_DIFFUSE;
4595                         if (specularscale > 0)
4596                         {
4597                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4598                                 if (r_shadow_glossexact.integer)
4599                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4600                         }
4601                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4602                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4603                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4604                         else
4605                                 R_Mesh_ColorPointer(NULL, 0, 0);
4606                 }
4607                 else if (rsurface.uselightmaptexture)
4608                 {
4609                         // ordinary lightmapping (q1bsp, q3bsp)
4610                         mode = SHADERMODE_LIGHTMAP;
4611                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4612                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4613                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4614                         else
4615                                 R_Mesh_ColorPointer(NULL, 0, 0);
4616                 }
4617                 else
4618                 {
4619                         // ordinary vertex coloring (q3bsp)
4620                         mode = SHADERMODE_VERTEXCOLOR;
4621                         R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4622                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4623                 }
4624                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4625                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4626                 {
4627                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4628                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4629                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4630                 }
4631                 else
4632                 {
4633                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4634                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4635                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4636                 }
4637                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4638                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4639         }
4640         switch(vid.renderpath)
4641         {
4642         case RENDERPATH_GL20:
4643                 R_SetupShader_SetPermutationGLSL(mode, permutation);
4644                 if (mode == SHADERMODE_LIGHTSOURCE)
4645                 {
4646                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
4647                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
4648                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
4649                         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);
4650                         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);
4651                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
4652         
4653                         // additive passes are only darkened by fog, not tinted
4654                         if (r_glsl_permutation->loc_FogColor >= 0)
4655                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4656                         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]);
4657                         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]);
4658                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4659                 }
4660                 else
4661                 {
4662                         if (mode == SHADERMODE_FLATCOLOR)
4663                         {
4664                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
4665                         }
4666                         else if (mode == SHADERMODE_LIGHTDIRECTION)
4667                         {
4668                                 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]);
4669                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * rsurface.colormod[0], r_refdef.lightmapintensity * rsurface.colormod[1], r_refdef.lightmapintensity * rsurface.colormod[2]);
4670                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
4671                                 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);
4672                                 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);
4673                                 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]);
4674                                 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]);
4675                         }
4676                         else
4677                         {
4678                                 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]);
4679                                 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]);
4680                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
4681                                 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);
4682                                 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);
4683                         }
4684                         // additive passes are only darkened by fog, not tinted
4685                         if (r_glsl_permutation->loc_FogColor >= 0)
4686                         {
4687                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4688                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4689                                 else
4690                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4691                         }
4692                         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);
4693                         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]);
4694                         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]);
4695                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
4696                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
4697                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
4698                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
4699                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4700                 }
4701                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
4702                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
4703                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
4704                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
4705                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
4706                 if (r_glsl_permutation->loc_Color_Pants >= 0)
4707                 {
4708                         if (rsurface.texture->pantstexture)
4709                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4710                         else
4711                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
4712                 }
4713                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
4714                 {
4715                         if (rsurface.texture->shirttexture)
4716                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4717                         else
4718                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
4719                 }
4720                 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]);
4721                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
4722                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
4723                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
4724                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
4725                 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]);
4726
4727         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
4728         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
4729         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
4730                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
4731                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
4732                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
4733                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
4734                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
4735                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
4736                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
4737                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
4738                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
4739                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
4740                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
4741                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_white                                     );
4742                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_blanknormalmap                            );
4743                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
4744                 if (r_glsl_permutation->loc_Texture_Refraction      >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , r_texture_white                                     );
4745                 if (r_glsl_permutation->loc_Texture_Reflection      >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , r_texture_white                                     );
4746                 if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
4747                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
4748                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
4749                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
4750                 if (rsurface.rtlight)
4751                 {
4752                         if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
4753                         if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT     , r_shadow_shadowmaprectangletexture                  );
4754                         if (r_shadow_usingshadowmapcube)
4755                                 if (r_glsl_permutation->loc_Texture_ShadowMapCube   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE     , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
4756                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D       , r_shadow_shadowmap2dtexture                         );
4757                         if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
4758                 }
4759                 CHECKGLERROR
4760                 break;
4761         case RENDERPATH_CGGL:
4762 #ifdef SUPPORTCG
4763                 R_SetupShader_SetPermutationCG(mode, permutation);
4764                 if (mode == SHADERMODE_LIGHTSOURCE)
4765                 {
4766                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
4767                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4768                 }
4769                 else
4770                 {
4771                         if (mode == SHADERMODE_LIGHTDIRECTION)
4772                         {
4773                                 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
4774                         }
4775                 }
4776                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
4777                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
4778                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4779                 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
4780                 CHECKGLERROR
4781
4782                 if (mode == SHADERMODE_LIGHTSOURCE)
4783                 {
4784                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4785                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
4786                         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
4787                         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
4788                         if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);CHECKCGERROR
4789
4790                         // additive passes are only darkened by fog, not tinted
4791                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
4792                         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
4793                         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
4794                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4795                 }
4796                 else
4797                 {
4798                         if (mode == SHADERMODE_FLATCOLOR)
4799                         {
4800                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);CHECKCGERROR
4801                         }
4802                         else if (mode == SHADERMODE_LIGHTDIRECTION)
4803                         {
4804                                 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
4805                                 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, r_refdef.lightmapintensity * rsurface.colormod[0], r_refdef.lightmapintensity * rsurface.colormod[1], r_refdef.lightmapintensity * rsurface.colormod[2]);CHECKCGERROR
4806                                 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);CHECKCGERROR
4807                                 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
4808                                 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
4809                                 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
4810                                 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
4811                         }
4812                         else
4813                         {
4814                                 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
4815                                 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
4816                                 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);CHECKCGERROR
4817                                 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
4818                                 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
4819                         }
4820                         // additive passes are only darkened by fog, not tinted
4821                         if (r_cg_permutation->fp_FogColor)
4822                         {
4823                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4824                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
4825                                 else
4826                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4827                                 CHECKCGERROR
4828                         }
4829                         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
4830                         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
4831                         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
4832                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
4833                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
4834                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
4835                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
4836                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4837                 }
4838                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
4839                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
4840                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4841                 if (r_cg_permutation->fp_Color_Pants)
4842                 {
4843                         if (rsurface.texture->pantstexture)
4844                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4845                         else
4846                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
4847                         CHECKCGERROR
4848                 }
4849                 if (r_cg_permutation->fp_Color_Shirt)
4850                 {
4851                         if (rsurface.texture->shirttexture)
4852                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4853                         else
4854                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
4855                         CHECKCGERROR
4856                 }
4857                 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
4858                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
4859                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
4860                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
4861                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
4862                 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
4863
4864         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
4865         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
4866         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
4867                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
4868                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
4869                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
4870                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
4871                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
4872                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
4873                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
4874                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
4875                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
4876                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
4877                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
4878                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , r_texture_white                                     );CHECKCGERROR
4879                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , r_texture_blanknormalmap                            );CHECKCGERROR
4880                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
4881                 if (r_cg_permutation->fp_Texture_Refraction     ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction     , r_texture_white                                     );CHECKCGERROR
4882                 if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , r_texture_white                                     );CHECKCGERROR
4883                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
4884                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
4885                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
4886                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
4887                 if (rsurface.rtlight)
4888                 {
4889                         if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
4890                         if (r_cg_permutation->fp_Texture_ShadowMapRect  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
4891                         if (r_shadow_usingshadowmapcube)
4892                                 if (r_cg_permutation->fp_Texture_ShadowMapCube  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
4893                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
4894                         if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
4895                 }
4896
4897                 CHECKGLERROR
4898 #endif
4899                 break;
4900         case RENDERPATH_GL13:
4901         case RENDERPATH_GL11:
4902                 break;
4903         }
4904 }
4905
4906 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
4907 {
4908         // select a permutation of the lighting shader appropriate to this
4909         // combination of texture, entity, light source, and fogging, only use the
4910         // minimum features necessary to avoid wasting rendering time in the
4911         // fragment shader on features that are not being used
4912         unsigned int permutation = 0;
4913         unsigned int mode = 0;
4914         const float *lightcolorbase = rtlight->currentcolor;
4915         float ambientscale = rtlight->ambientscale;
4916         float diffusescale = rtlight->diffusescale;
4917         float specularscale = rtlight->specularscale;
4918         // this is the location of the light in view space
4919         vec3_t viewlightorigin;
4920         // this transforms from view space (camera) to light space (cubemap)
4921         matrix4x4_t viewtolight;
4922         matrix4x4_t lighttoview;
4923         float viewtolight16f[16];
4924         float range = 1.0f / r_shadow_deferred_8bitrange.value;
4925         // light source
4926         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
4927         if (rtlight->currentcubemap != r_texture_whitecube)
4928                 permutation |= SHADERPERMUTATION_CUBEFILTER;
4929         if (diffusescale > 0)
4930                 permutation |= SHADERPERMUTATION_DIFFUSE;
4931         if (specularscale > 0)
4932         {
4933                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4934                 if (r_shadow_glossexact.integer)
4935                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4936         }
4937         if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4938         {
4939                 if (r_shadow_usingshadowmaprect)
4940                         permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4941                 if (r_shadow_usingshadowmap2d)
4942                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4943                 if (r_shadow_usingshadowmapcube)
4944                         permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4945                 else if(r_shadow_shadowmapvsdct)
4946                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4947
4948                 if (r_shadow_shadowmapsampler)
4949                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4950                 if (r_shadow_shadowmappcf > 1)
4951                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4952                 else if (r_shadow_shadowmappcf)
4953                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4954         }
4955         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
4956         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
4957         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
4958         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
4959         switch(vid.renderpath)
4960         {
4961         case RENDERPATH_GL20:
4962                 R_SetupShader_SetPermutationGLSL(mode, permutation);
4963                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
4964                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
4965                 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);
4966                 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);
4967                 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);
4968                 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]);
4969                 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]);
4970                 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));
4971                 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]);
4972
4973                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
4974                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
4975                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
4976                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
4977                 if (r_glsl_permutation->loc_Texture_ShadowMapRect     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT      , r_shadow_shadowmaprectangletexture                  );
4978                 if (r_shadow_usingshadowmapcube)
4979                         if (r_glsl_permutation->loc_Texture_ShadowMapCube     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE      , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
4980                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
4981                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
4982                 break;
4983         case RENDERPATH_CGGL:
4984 #ifdef SUPPORTCG
4985                 R_SetupShader_SetPermutationCG(mode, permutation);
4986                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
4987                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
4988                 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
4989                 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
4990                 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
4991                 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
4992                 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
4993                 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
4994                 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
4995
4996                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
4997                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
4998                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
4999                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
5000                 if (r_cg_permutation->fp_Texture_ShadowMapRect    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
5001                 if (r_shadow_usingshadowmapcube)
5002                         if (r_cg_permutation->fp_Texture_ShadowMapCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5003                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5004                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
5005 #endif
5006                 break;
5007         case RENDERPATH_GL13:
5008         case RENDERPATH_GL11:
5009                 break;
5010         }
5011 }
5012
5013 #define SKINFRAME_HASH 1024
5014
5015 typedef struct
5016 {
5017         int loadsequence; // incremented each level change
5018         memexpandablearray_t array;
5019         skinframe_t *hash[SKINFRAME_HASH];
5020 }
5021 r_skinframe_t;
5022 r_skinframe_t r_skinframe;
5023
5024 void R_SkinFrame_PrepareForPurge(void)
5025 {
5026         r_skinframe.loadsequence++;
5027         // wrap it without hitting zero
5028         if (r_skinframe.loadsequence >= 200)
5029                 r_skinframe.loadsequence = 1;
5030 }
5031
5032 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5033 {
5034         if (!skinframe)
5035                 return;
5036         // mark the skinframe as used for the purging code
5037         skinframe->loadsequence = r_skinframe.loadsequence;
5038 }
5039
5040 void R_SkinFrame_Purge(void)
5041 {
5042         int i;
5043         skinframe_t *s;
5044         for (i = 0;i < SKINFRAME_HASH;i++)
5045         {
5046                 for (s = r_skinframe.hash[i];s;s = s->next)
5047                 {
5048                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5049                         {
5050                                 if (s->merged == s->base)
5051                                         s->merged = NULL;
5052                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5053                                 R_PurgeTexture(s->stain );s->stain  = NULL;
5054                                 R_PurgeTexture(s->merged);s->merged = NULL;
5055                                 R_PurgeTexture(s->base  );s->base   = NULL;
5056                                 R_PurgeTexture(s->pants );s->pants  = NULL;
5057                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
5058                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
5059                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
5060                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
5061                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
5062                                 s->loadsequence = 0;
5063                         }
5064                 }
5065         }
5066 }
5067
5068 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5069         skinframe_t *item;
5070         char basename[MAX_QPATH];
5071
5072         Image_StripImageExtension(name, basename, sizeof(basename));
5073
5074         if( last == NULL ) {
5075                 int hashindex;
5076                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5077                 item = r_skinframe.hash[hashindex];
5078         } else {
5079                 item = last->next;
5080         }
5081
5082         // linearly search through the hash bucket
5083         for( ; item ; item = item->next ) {
5084                 if( !strcmp( item->basename, basename ) ) {
5085                         return item;
5086                 }
5087         }
5088         return NULL;
5089 }
5090
5091 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5092 {
5093         skinframe_t *item;
5094         int hashindex;
5095         char basename[MAX_QPATH];
5096
5097         Image_StripImageExtension(name, basename, sizeof(basename));
5098
5099         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5100         for (item = r_skinframe.hash[hashindex];item;item = item->next)
5101                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5102                         break;
5103
5104         if (!item) {
5105                 rtexture_t *dyntexture;
5106                 // check whether its a dynamic texture
5107                 dyntexture = CL_GetDynTexture( basename );
5108                 if (!add && !dyntexture)
5109                         return NULL;
5110                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5111                 memset(item, 0, sizeof(*item));
5112                 strlcpy(item->basename, basename, sizeof(item->basename));
5113                 item->base = dyntexture; // either NULL or dyntexture handle
5114                 item->textureflags = textureflags;
5115                 item->comparewidth = comparewidth;
5116                 item->compareheight = compareheight;
5117                 item->comparecrc = comparecrc;
5118                 item->next = r_skinframe.hash[hashindex];
5119                 r_skinframe.hash[hashindex] = item;
5120         }
5121         else if( item->base == NULL )
5122         {
5123                 rtexture_t *dyntexture;
5124                 // check whether its a dynamic texture
5125                 // 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]
5126                 dyntexture = CL_GetDynTexture( basename );
5127                 item->base = dyntexture; // either NULL or dyntexture handle
5128         }
5129
5130         R_SkinFrame_MarkUsed(item);
5131         return item;
5132 }
5133
5134 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5135         { \
5136                 unsigned long long avgcolor[5], wsum; \
5137                 int pix, comp, w; \
5138                 avgcolor[0] = 0; \
5139                 avgcolor[1] = 0; \
5140                 avgcolor[2] = 0; \
5141                 avgcolor[3] = 0; \
5142                 avgcolor[4] = 0; \
5143                 wsum = 0; \
5144                 for(pix = 0; pix < cnt; ++pix) \
5145                 { \
5146                         w = 0; \
5147                         for(comp = 0; comp < 3; ++comp) \
5148                                 w += getpixel; \
5149                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5150                         { \
5151                                 ++wsum; \
5152                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5153                                 w = getpixel; \
5154                                 for(comp = 0; comp < 3; ++comp) \
5155                                         avgcolor[comp] += getpixel * w; \
5156                                 avgcolor[3] += w; \
5157                         } \
5158                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5159                         avgcolor[4] += getpixel; \
5160                 } \
5161                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5162                         avgcolor[3] = 1; \
5163                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5164                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5165                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5166                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5167         }
5168
5169 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5170 {
5171         int j;
5172         unsigned char *pixels;
5173         unsigned char *bumppixels;
5174         unsigned char *basepixels = NULL;
5175         int basepixels_width = 0;
5176         int basepixels_height = 0;
5177         skinframe_t *skinframe;
5178         rtexture_t *ddsbase = NULL;
5179         qboolean ddshasalpha = false;
5180         float ddsavgcolor[4];
5181         char basename[MAX_QPATH];
5182
5183         if (cls.state == ca_dedicated)
5184                 return NULL;
5185
5186         // return an existing skinframe if already loaded
5187         // if loading of the first image fails, don't make a new skinframe as it
5188         // would cause all future lookups of this to be missing
5189         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5190         if (skinframe && skinframe->base)
5191                 return skinframe;
5192
5193         Image_StripImageExtension(name, basename, sizeof(basename));
5194
5195         // check for DDS texture file first
5196         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor)))
5197         {
5198                 basepixels = loadimagepixelsbgra(name, complain, true);
5199                 if (basepixels == NULL)
5200                         return NULL;
5201         }
5202
5203         if (developer_loading.integer)
5204                 Con_Printf("loading skin \"%s\"\n", name);
5205
5206         // we've got some pixels to store, so really allocate this new texture now
5207         if (!skinframe)
5208                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5209         skinframe->stain = NULL;
5210         skinframe->merged = NULL;
5211         skinframe->base = NULL;
5212         skinframe->pants = NULL;
5213         skinframe->shirt = NULL;
5214         skinframe->nmap = NULL;
5215         skinframe->gloss = NULL;
5216         skinframe->glow = NULL;
5217         skinframe->fog = NULL;
5218         skinframe->hasalpha = false;
5219
5220         if (ddsbase)
5221         {
5222                 skinframe->base = ddsbase;
5223                 skinframe->hasalpha = ddshasalpha;
5224                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5225                 if (r_loadfog && skinframe->hasalpha)
5226                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5227                 //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]);
5228         }
5229         else
5230         {
5231                 basepixels_width = image_width;
5232                 basepixels_height = image_height;
5233                 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);
5234                 if (textureflags & TEXF_ALPHA)
5235                 {
5236                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5237                         {
5238                                 if (basepixels[j] < 255)
5239                                 {
5240                                         skinframe->hasalpha = true;
5241                                         break;
5242                                 }
5243                         }
5244                         if (r_loadfog && skinframe->hasalpha)
5245                         {
5246                                 // has transparent pixels
5247                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5248                                 for (j = 0;j < image_width * image_height * 4;j += 4)
5249                                 {
5250                                         pixels[j+0] = 255;
5251                                         pixels[j+1] = 255;
5252                                         pixels[j+2] = 255;
5253                                         pixels[j+3] = basepixels[j+3];
5254                                 }
5255                                 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);
5256                                 Mem_Free(pixels);
5257                         }
5258                 }
5259                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5260                 //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]);
5261                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5262                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true);
5263                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
5264                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true);
5265         }
5266
5267         if (r_loaddds)
5268         {
5269                 if (r_loadnormalmap)
5270                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5271                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL);
5272                 if (r_loadgloss)
5273                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL);
5274                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL);
5275                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL);
5276         }
5277
5278         // _norm is the name used by tenebrae and has been adopted as standard
5279         if (r_loadnormalmap && skinframe->nmap == NULL)
5280         {
5281                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
5282                 {
5283                         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);
5284                         Mem_Free(pixels);
5285                         pixels = NULL;
5286                 }
5287                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
5288                 {
5289                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5290                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5291                         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);
5292                         Mem_Free(pixels);
5293                         Mem_Free(bumppixels);
5294                 }
5295                 else if (r_shadow_bumpscale_basetexture.value > 0)
5296                 {
5297                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5298                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5299                         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);
5300                         Mem_Free(pixels);
5301                 }
5302                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
5303                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true);
5304         }
5305
5306         // _luma is supported only for tenebrae compatibility
5307         // _glow is the preferred name
5308         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false))))
5309         {
5310                 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);
5311                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
5312                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true);
5313                 Mem_Free(pixels);pixels = NULL;
5314         }
5315
5316         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false)))
5317         {
5318                 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);
5319                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
5320                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true);
5321                 Mem_Free(pixels);
5322                 pixels = NULL;
5323         }
5324
5325         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false)))
5326         {
5327                 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);
5328                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
5329                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true);
5330                 Mem_Free(pixels);
5331                 pixels = NULL;
5332         }
5333
5334         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false)))
5335         {
5336                 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);
5337                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
5338                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true);
5339                 Mem_Free(pixels);
5340                 pixels = NULL;
5341         }
5342
5343         if (basepixels)
5344                 Mem_Free(basepixels);
5345
5346         return skinframe;
5347 }
5348
5349 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
5350 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
5351 {
5352         int i;
5353         unsigned char *temp1, *temp2;
5354         skinframe_t *skinframe;
5355
5356         if (cls.state == ca_dedicated)
5357                 return NULL;
5358
5359         // if already loaded just return it, otherwise make a new skinframe
5360         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
5361         if (skinframe && skinframe->base)
5362                 return skinframe;
5363
5364         skinframe->stain = NULL;
5365         skinframe->merged = NULL;
5366         skinframe->base = NULL;
5367         skinframe->pants = NULL;
5368         skinframe->shirt = NULL;
5369         skinframe->nmap = NULL;
5370         skinframe->gloss = NULL;
5371         skinframe->glow = NULL;
5372         skinframe->fog = NULL;
5373         skinframe->hasalpha = false;
5374
5375         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5376         if (!skindata)
5377                 return NULL;
5378
5379         if (developer_loading.integer)
5380                 Con_Printf("loading 32bit skin \"%s\"\n", name);
5381
5382         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
5383         {
5384                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5385                 temp2 = temp1 + width * height * 4;
5386                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5387                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5388                 Mem_Free(temp1);
5389         }
5390         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5391         if (textureflags & TEXF_ALPHA)
5392         {
5393                 for (i = 3;i < width * height * 4;i += 4)
5394                 {
5395                         if (skindata[i] < 255)
5396                         {
5397                                 skinframe->hasalpha = true;
5398                                 break;
5399                         }
5400                 }
5401                 if (r_loadfog && skinframe->hasalpha)
5402                 {
5403                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
5404                         memcpy(fogpixels, skindata, width * height * 4);
5405                         for (i = 0;i < width * height * 4;i += 4)
5406                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
5407                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5408                         Mem_Free(fogpixels);
5409                 }
5410         }
5411
5412         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
5413         //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]);
5414
5415         return skinframe;
5416 }
5417
5418 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
5419 {
5420         int i;
5421         int featuresmask;
5422         skinframe_t *skinframe;
5423
5424         if (cls.state == ca_dedicated)
5425                 return NULL;
5426
5427         // if already loaded just return it, otherwise make a new skinframe
5428         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5429         if (skinframe && skinframe->base)
5430                 return skinframe;
5431
5432         skinframe->stain = NULL;
5433         skinframe->merged = NULL;
5434         skinframe->base = NULL;
5435         skinframe->pants = NULL;
5436         skinframe->shirt = NULL;
5437         skinframe->nmap = NULL;
5438         skinframe->gloss = NULL;
5439         skinframe->glow = NULL;
5440         skinframe->fog = NULL;
5441         skinframe->hasalpha = false;
5442
5443         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5444         if (!skindata)
5445                 return NULL;
5446
5447         if (developer_loading.integer)
5448                 Con_Printf("loading quake skin \"%s\"\n", name);
5449
5450         // 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)
5451         skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
5452         memcpy(skinframe->qpixels, skindata, width*height);
5453         skinframe->qwidth = width;
5454         skinframe->qheight = height;
5455
5456         featuresmask = 0;
5457         for (i = 0;i < width * height;i++)
5458                 featuresmask |= palette_featureflags[skindata[i]];
5459
5460         skinframe->hasalpha = false;
5461         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
5462         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
5463         skinframe->qgeneratemerged = true;
5464         skinframe->qgeneratebase = skinframe->qhascolormapping;
5465         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
5466
5467         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
5468         //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]);
5469
5470         return skinframe;
5471 }
5472
5473 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
5474 {
5475         int width;
5476         int height;
5477         unsigned char *skindata;
5478
5479         if (!skinframe->qpixels)
5480                 return;
5481
5482         if (!skinframe->qhascolormapping)
5483                 colormapped = false;
5484
5485         if (colormapped)
5486         {
5487                 if (!skinframe->qgeneratebase)
5488                         return;
5489         }
5490         else
5491         {
5492                 if (!skinframe->qgeneratemerged)
5493                         return;
5494         }
5495
5496         width = skinframe->qwidth;
5497         height = skinframe->qheight;
5498         skindata = skinframe->qpixels;
5499
5500         if (skinframe->qgeneratenmap)
5501         {
5502                 unsigned char *temp1, *temp2;
5503                 skinframe->qgeneratenmap = false;
5504                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5505                 temp2 = temp1 + width * height * 4;
5506                 // use either a custom palette or the quake palette
5507                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
5508                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5509                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5510                 Mem_Free(temp1);
5511         }
5512
5513         if (skinframe->qgenerateglow)
5514         {
5515                 skinframe->qgenerateglow = false;
5516                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
5517         }
5518
5519         if (colormapped)
5520         {
5521                 skinframe->qgeneratebase = false;
5522                 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);
5523                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
5524                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
5525         }
5526         else
5527         {
5528                 skinframe->qgeneratemerged = false;
5529                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
5530         }
5531
5532         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
5533         {
5534                 Mem_Free(skinframe->qpixels);
5535                 skinframe->qpixels = NULL;
5536         }
5537 }
5538
5539 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)
5540 {
5541         int i;
5542         skinframe_t *skinframe;
5543
5544         if (cls.state == ca_dedicated)
5545                 return NULL;
5546
5547         // if already loaded just return it, otherwise make a new skinframe
5548         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5549         if (skinframe && skinframe->base)
5550                 return skinframe;
5551
5552         skinframe->stain = NULL;
5553         skinframe->merged = NULL;
5554         skinframe->base = NULL;
5555         skinframe->pants = NULL;
5556         skinframe->shirt = NULL;
5557         skinframe->nmap = NULL;
5558         skinframe->gloss = NULL;
5559         skinframe->glow = NULL;
5560         skinframe->fog = NULL;
5561         skinframe->hasalpha = false;
5562
5563         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5564         if (!skindata)
5565                 return NULL;
5566
5567         if (developer_loading.integer)
5568                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
5569
5570         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
5571         if (textureflags & TEXF_ALPHA)
5572         {
5573                 for (i = 0;i < width * height;i++)
5574                 {
5575                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
5576                         {
5577                                 skinframe->hasalpha = true;
5578                                 break;
5579                         }
5580                 }
5581                 if (r_loadfog && skinframe->hasalpha)
5582                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
5583         }
5584
5585         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
5586         //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]);
5587
5588         return skinframe;
5589 }
5590
5591 skinframe_t *R_SkinFrame_LoadMissing(void)
5592 {
5593         skinframe_t *skinframe;
5594
5595         if (cls.state == ca_dedicated)
5596                 return NULL;
5597
5598         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
5599         skinframe->stain = NULL;
5600         skinframe->merged = NULL;
5601         skinframe->base = NULL;
5602         skinframe->pants = NULL;
5603         skinframe->shirt = NULL;
5604         skinframe->nmap = NULL;
5605         skinframe->gloss = NULL;
5606         skinframe->glow = NULL;
5607         skinframe->fog = NULL;
5608         skinframe->hasalpha = false;
5609
5610         skinframe->avgcolor[0] = rand() / RAND_MAX;
5611         skinframe->avgcolor[1] = rand() / RAND_MAX;
5612         skinframe->avgcolor[2] = rand() / RAND_MAX;
5613         skinframe->avgcolor[3] = 1;
5614
5615         return skinframe;
5616 }
5617
5618 void R_Main_FreeViewCache(void)
5619 {
5620         if (r_refdef.viewcache.entityvisible)
5621                 Mem_Free(r_refdef.viewcache.entityvisible);
5622         if (r_refdef.viewcache.world_pvsbits)
5623                 Mem_Free(r_refdef.viewcache.world_pvsbits);
5624         if (r_refdef.viewcache.world_leafvisible)
5625                 Mem_Free(r_refdef.viewcache.world_leafvisible);
5626         if (r_refdef.viewcache.world_surfacevisible)
5627                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
5628         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
5629 }
5630
5631 void R_Main_ResizeViewCache(void)
5632 {
5633         int numentities = r_refdef.scene.numentities;
5634         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
5635         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
5636         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
5637         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
5638         if (r_refdef.viewcache.maxentities < numentities)
5639         {
5640                 r_refdef.viewcache.maxentities = numentities;
5641                 if (r_refdef.viewcache.entityvisible)
5642                         Mem_Free(r_refdef.viewcache.entityvisible);
5643                 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
5644         }
5645         if (r_refdef.viewcache.world_numclusters != numclusters)
5646         {
5647                 r_refdef.viewcache.world_numclusters = numclusters;
5648                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
5649                 if (r_refdef.viewcache.world_pvsbits)
5650                         Mem_Free(r_refdef.viewcache.world_pvsbits);
5651                 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
5652         }
5653         if (r_refdef.viewcache.world_numleafs != numleafs)
5654         {
5655                 r_refdef.viewcache.world_numleafs = numleafs;
5656                 if (r_refdef.viewcache.world_leafvisible)
5657                         Mem_Free(r_refdef.viewcache.world_leafvisible);
5658                 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
5659         }
5660         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
5661         {
5662                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
5663                 if (r_refdef.viewcache.world_surfacevisible)
5664                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
5665                 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
5666         }
5667 }
5668
5669 extern rtexture_t *loadingscreentexture;
5670 void gl_main_start(void)
5671 {
5672         loadingscreentexture = NULL;
5673         r_texture_blanknormalmap = NULL;
5674         r_texture_white = NULL;
5675         r_texture_grey128 = NULL;
5676         r_texture_black = NULL;
5677         r_texture_whitecube = NULL;
5678         r_texture_normalizationcube = NULL;
5679         r_texture_fogattenuation = NULL;
5680         r_texture_gammaramps = NULL;
5681
5682         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
5683         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
5684
5685         switch(vid.renderpath)
5686         {
5687         case RENDERPATH_GL20:
5688         case RENDERPATH_CGGL:
5689                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5690                 Cvar_SetValueQuick(&gl_combine, 1);
5691                 Cvar_SetValueQuick(&r_glsl, 1);
5692                 r_loadnormalmap = true;
5693                 r_loadgloss = true;
5694                 r_loadfog = false;
5695                 break;
5696         case RENDERPATH_GL13:
5697                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5698                 Cvar_SetValueQuick(&gl_combine, 1);
5699                 Cvar_SetValueQuick(&r_glsl, 0);
5700                 r_loadnormalmap = false;
5701                 r_loadgloss = false;
5702                 r_loadfog = true;
5703                 break;
5704         case RENDERPATH_GL11:
5705                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5706                 Cvar_SetValueQuick(&gl_combine, 0);
5707                 Cvar_SetValueQuick(&r_glsl, 0);
5708                 r_loadnormalmap = false;
5709                 r_loadgloss = false;
5710                 r_loadfog = true;
5711                 break;
5712         }
5713
5714         R_AnimCache_Free();
5715         R_FrameData_Reset();
5716
5717         r_numqueries = 0;
5718         r_maxqueries = 0;
5719         memset(r_queries, 0, sizeof(r_queries));
5720
5721         r_qwskincache = NULL;
5722         r_qwskincache_size = 0;
5723
5724         // set up r_skinframe loading system for textures
5725         memset(&r_skinframe, 0, sizeof(r_skinframe));
5726         r_skinframe.loadsequence = 1;
5727         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
5728
5729         r_main_texturepool = R_AllocTexturePool();
5730         R_BuildBlankTextures();
5731         R_BuildNoTexture();
5732         if (vid.support.arb_texture_cube_map)
5733         {
5734                 R_BuildWhiteCube();
5735                 R_BuildNormalizationCube();
5736         }
5737         r_texture_fogattenuation = NULL;
5738         r_texture_gammaramps = NULL;
5739         //r_texture_fogintensity = NULL;
5740         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
5741         memset(&r_waterstate, 0, sizeof(r_waterstate));
5742         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5743         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
5744 #ifdef SUPPORTCG
5745         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5746         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
5747 #endif
5748         memset(&r_svbsp, 0, sizeof (r_svbsp));
5749
5750         r_refdef.fogmasktable_density = 0;
5751 }
5752
5753 void gl_main_shutdown(void)
5754 {
5755         R_AnimCache_Free();
5756         R_FrameData_Reset();
5757
5758         R_Main_FreeViewCache();
5759
5760         if (r_maxqueries)
5761                 qglDeleteQueriesARB(r_maxqueries, r_queries);
5762
5763         r_numqueries = 0;
5764         r_maxqueries = 0;
5765         memset(r_queries, 0, sizeof(r_queries));
5766
5767         r_qwskincache = NULL;
5768         r_qwskincache_size = 0;
5769
5770         // clear out the r_skinframe state
5771         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
5772         memset(&r_skinframe, 0, sizeof(r_skinframe));
5773
5774         if (r_svbsp.nodes)
5775                 Mem_Free(r_svbsp.nodes);
5776         memset(&r_svbsp, 0, sizeof (r_svbsp));
5777         R_FreeTexturePool(&r_main_texturepool);
5778         loadingscreentexture = NULL;
5779         r_texture_blanknormalmap = NULL;
5780         r_texture_white = NULL;
5781         r_texture_grey128 = NULL;
5782         r_texture_black = NULL;
5783         r_texture_whitecube = NULL;
5784         r_texture_normalizationcube = NULL;
5785         r_texture_fogattenuation = NULL;
5786         r_texture_gammaramps = NULL;
5787         //r_texture_fogintensity = NULL;
5788         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
5789         memset(&r_waterstate, 0, sizeof(r_waterstate));
5790         R_GLSL_Restart_f();
5791 }
5792
5793 extern void CL_ParseEntityLump(char *entitystring);
5794 void gl_main_newmap(void)
5795 {
5796         // FIXME: move this code to client
5797         int l;
5798         char *entities, entname[MAX_QPATH];
5799         if (r_qwskincache)
5800                 Mem_Free(r_qwskincache);
5801         r_qwskincache = NULL;
5802         r_qwskincache_size = 0;
5803         if (cl.worldmodel)
5804         {
5805                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
5806                 l = (int)strlen(entname) - 4;
5807                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
5808                 {
5809                         memcpy(entname + l, ".ent", 5);
5810                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
5811                         {
5812                                 CL_ParseEntityLump(entities);
5813                                 Mem_Free(entities);
5814                                 return;
5815                         }
5816                 }
5817                 if (cl.worldmodel->brush.entities)
5818                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
5819         }
5820         R_Main_FreeViewCache();
5821
5822         R_FrameData_Reset();
5823 }
5824
5825 void GL_Main_Init(void)
5826 {
5827         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
5828
5829         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
5830         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
5831         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
5832         if (gamemode == GAME_NEHAHRA)
5833         {
5834                 Cvar_RegisterVariable (&gl_fogenable);
5835                 Cvar_RegisterVariable (&gl_fogdensity);
5836                 Cvar_RegisterVariable (&gl_fogred);
5837                 Cvar_RegisterVariable (&gl_foggreen);
5838                 Cvar_RegisterVariable (&gl_fogblue);
5839                 Cvar_RegisterVariable (&gl_fogstart);
5840                 Cvar_RegisterVariable (&gl_fogend);
5841                 Cvar_RegisterVariable (&gl_skyclip);
5842         }
5843         Cvar_RegisterVariable(&r_motionblur);
5844         Cvar_RegisterVariable(&r_motionblur_maxblur);
5845         Cvar_RegisterVariable(&r_motionblur_bmin);
5846         Cvar_RegisterVariable(&r_motionblur_vmin);
5847         Cvar_RegisterVariable(&r_motionblur_vmax);
5848         Cvar_RegisterVariable(&r_motionblur_vcoeff);
5849         Cvar_RegisterVariable(&r_motionblur_randomize);
5850         Cvar_RegisterVariable(&r_damageblur);
5851         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
5852         Cvar_RegisterVariable(&r_equalize_entities_minambient);
5853         Cvar_RegisterVariable(&r_equalize_entities_by);
5854         Cvar_RegisterVariable(&r_equalize_entities_to);
5855         Cvar_RegisterVariable(&r_depthfirst);
5856         Cvar_RegisterVariable(&r_useinfinitefarclip);
5857         Cvar_RegisterVariable(&r_farclip_base);
5858         Cvar_RegisterVariable(&r_farclip_world);
5859         Cvar_RegisterVariable(&r_nearclip);
5860         Cvar_RegisterVariable(&r_showbboxes);
5861         Cvar_RegisterVariable(&r_showsurfaces);
5862         Cvar_RegisterVariable(&r_showtris);
5863         Cvar_RegisterVariable(&r_shownormals);
5864         Cvar_RegisterVariable(&r_showlighting);
5865         Cvar_RegisterVariable(&r_showshadowvolumes);
5866         Cvar_RegisterVariable(&r_showcollisionbrushes);
5867         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
5868         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
5869         Cvar_RegisterVariable(&r_showdisabledepthtest);
5870         Cvar_RegisterVariable(&r_drawportals);
5871         Cvar_RegisterVariable(&r_drawentities);
5872         Cvar_RegisterVariable(&r_cullentities_trace);
5873         Cvar_RegisterVariable(&r_cullentities_trace_samples);
5874         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
5875         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
5876         Cvar_RegisterVariable(&r_cullentities_trace_delay);
5877         Cvar_RegisterVariable(&r_drawviewmodel);
5878         Cvar_RegisterVariable(&r_speeds);
5879         Cvar_RegisterVariable(&r_fullbrights);
5880         Cvar_RegisterVariable(&r_wateralpha);
5881         Cvar_RegisterVariable(&r_dynamic);
5882         Cvar_RegisterVariable(&r_fullbright);
5883         Cvar_RegisterVariable(&r_shadows);
5884         Cvar_RegisterVariable(&r_shadows_darken);
5885         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
5886         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
5887         Cvar_RegisterVariable(&r_shadows_throwdistance);
5888         Cvar_RegisterVariable(&r_shadows_throwdirection);
5889         Cvar_RegisterVariable(&r_q1bsp_skymasking);
5890         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
5891         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
5892         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
5893         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
5894         Cvar_RegisterVariable(&r_fog_exp2);
5895         Cvar_RegisterVariable(&r_drawfog);
5896         Cvar_RegisterVariable(&r_transparentdepthmasking);
5897         Cvar_RegisterVariable(&r_texture_dds_load);
5898         Cvar_RegisterVariable(&r_texture_dds_save);
5899         Cvar_RegisterVariable(&r_textureunits);
5900         Cvar_RegisterVariable(&gl_combine);
5901         Cvar_RegisterVariable(&r_glsl);
5902         Cvar_RegisterVariable(&r_glsl_deluxemapping);
5903         Cvar_RegisterVariable(&r_glsl_offsetmapping);
5904         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
5905         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
5906         Cvar_RegisterVariable(&r_glsl_postprocess);
5907         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
5908         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
5909         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
5910         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
5911         Cvar_RegisterVariable(&r_water);
5912         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
5913         Cvar_RegisterVariable(&r_water_clippingplanebias);
5914         Cvar_RegisterVariable(&r_water_refractdistort);
5915         Cvar_RegisterVariable(&r_water_reflectdistort);
5916         Cvar_RegisterVariable(&r_lerpsprites);
5917         Cvar_RegisterVariable(&r_lerpmodels);
5918         Cvar_RegisterVariable(&r_lerplightstyles);
5919         Cvar_RegisterVariable(&r_waterscroll);
5920         Cvar_RegisterVariable(&r_bloom);
5921         Cvar_RegisterVariable(&r_bloom_colorscale);
5922         Cvar_RegisterVariable(&r_bloom_brighten);
5923         Cvar_RegisterVariable(&r_bloom_blur);
5924         Cvar_RegisterVariable(&r_bloom_resolution);
5925         Cvar_RegisterVariable(&r_bloom_colorexponent);
5926         Cvar_RegisterVariable(&r_bloom_colorsubtract);
5927         Cvar_RegisterVariable(&r_hdr);
5928         Cvar_RegisterVariable(&r_hdr_scenebrightness);
5929         Cvar_RegisterVariable(&r_hdr_glowintensity);
5930         Cvar_RegisterVariable(&r_hdr_range);
5931         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
5932         Cvar_RegisterVariable(&developer_texturelogging);
5933         Cvar_RegisterVariable(&gl_lightmaps);
5934         Cvar_RegisterVariable(&r_test);
5935         Cvar_RegisterVariable(&r_batchmode);
5936         Cvar_RegisterVariable(&r_glsl_saturation);
5937         Cvar_RegisterVariable(&r_framedatasize);
5938         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
5939                 Cvar_SetValue("r_fullbrights", 0);
5940         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
5941
5942         Cvar_RegisterVariable(&r_track_sprites);
5943         Cvar_RegisterVariable(&r_track_sprites_flags);
5944         Cvar_RegisterVariable(&r_track_sprites_scalew);
5945         Cvar_RegisterVariable(&r_track_sprites_scaleh);
5946 }
5947
5948 extern void R_Textures_Init(void);
5949 extern void GL_Draw_Init(void);
5950 extern void GL_Main_Init(void);
5951 extern void R_Shadow_Init(void);
5952 extern void R_Sky_Init(void);
5953 extern void GL_Surf_Init(void);
5954 extern void R_Particles_Init(void);
5955 extern void R_Explosion_Init(void);
5956 extern void gl_backend_init(void);
5957 extern void Sbar_Init(void);
5958 extern void R_LightningBeams_Init(void);
5959 extern void Mod_RenderInit(void);
5960 extern void Font_Init(void);
5961
5962 void Render_Init(void)
5963 {
5964         gl_backend_init();
5965         R_Textures_Init();
5966         GL_Main_Init();
5967         Font_Init();
5968         GL_Draw_Init();
5969         R_Shadow_Init();
5970         R_Sky_Init();
5971         GL_Surf_Init();
5972         Sbar_Init();
5973         R_Particles_Init();
5974         R_Explosion_Init();
5975         R_LightningBeams_Init();
5976         Mod_RenderInit();
5977 }
5978
5979 /*
5980 ===============
5981 GL_Init
5982 ===============
5983 */
5984 extern char *ENGINE_EXTENSIONS;
5985 void GL_Init (void)
5986 {
5987         gl_renderer = (const char *)qglGetString(GL_RENDERER);
5988         gl_vendor = (const char *)qglGetString(GL_VENDOR);
5989         gl_version = (const char *)qglGetString(GL_VERSION);
5990         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
5991
5992         if (!gl_extensions)
5993                 gl_extensions = "";
5994         if (!gl_platformextensions)
5995                 gl_platformextensions = "";
5996
5997         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
5998         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
5999         Con_Printf("GL_VERSION: %s\n", gl_version);
6000         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
6001         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
6002
6003         VID_CheckExtensions();
6004
6005         // LordHavoc: report supported extensions
6006         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
6007
6008         // clear to black (loading plaque will be seen over this)
6009         CHECKGLERROR
6010         qglClearColor(0,0,0,1);CHECKGLERROR
6011         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
6012 }
6013
6014 int R_CullBox(const vec3_t mins, const vec3_t maxs)
6015 {
6016         int i;
6017         mplane_t *p;
6018         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6019         {
6020                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
6021                 if (i == 4)
6022                         continue;
6023                 p = r_refdef.view.frustum + i;
6024                 switch(p->signbits)
6025                 {
6026                 default:
6027                 case 0:
6028                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6029                                 return true;
6030                         break;
6031                 case 1:
6032                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6033                                 return true;
6034                         break;
6035                 case 2:
6036                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6037                                 return true;
6038                         break;
6039                 case 3:
6040                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6041                                 return true;
6042                         break;
6043                 case 4:
6044                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6045                                 return true;
6046                         break;
6047                 case 5:
6048                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6049                                 return true;
6050                         break;
6051                 case 6:
6052                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6053                                 return true;
6054                         break;
6055                 case 7:
6056                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6057                                 return true;
6058                         break;
6059                 }
6060         }
6061         return false;
6062 }
6063
6064 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
6065 {
6066         int i;
6067         const mplane_t *p;
6068         for (i = 0;i < numplanes;i++)
6069         {
6070                 p = planes + i;
6071                 switch(p->signbits)
6072                 {
6073                 default:
6074                 case 0:
6075                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6076                                 return true;
6077                         break;
6078                 case 1:
6079                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6080                                 return true;
6081                         break;
6082                 case 2:
6083                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6084                                 return true;
6085                         break;
6086                 case 3:
6087                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6088                                 return true;
6089                         break;
6090                 case 4:
6091                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6092                                 return true;
6093                         break;
6094                 case 5:
6095                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6096                                 return true;
6097                         break;
6098                 case 6:
6099                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6100                                 return true;
6101                         break;
6102                 case 7:
6103                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6104                                 return true;
6105                         break;
6106                 }
6107         }
6108         return false;
6109 }
6110
6111 //==================================================================================
6112
6113 // LordHavoc: this stores temporary data used within the same frame
6114
6115 qboolean r_framedata_failed;
6116 static size_t r_framedata_size;
6117 static size_t r_framedata_current;
6118 static void *r_framedata_base;
6119
6120 void R_FrameData_Reset(void)
6121 {
6122         if (r_framedata_base)
6123                 Mem_Free(r_framedata_base);
6124         r_framedata_base = NULL;
6125         r_framedata_size = 0;
6126         r_framedata_current = 0;
6127         r_framedata_failed = false;
6128 }
6129
6130 void R_FrameData_NewFrame(void)
6131 {
6132         size_t wantedsize;
6133         if (r_framedata_failed)
6134                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
6135         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
6136         wantedsize = bound(65536, wantedsize, 128*1024*1024);
6137         if (r_framedata_size != wantedsize)
6138         {
6139                 r_framedata_size = wantedsize;
6140                 if (r_framedata_base)
6141                         Mem_Free(r_framedata_base);
6142                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
6143         }
6144         r_framedata_current = 0;
6145         r_framedata_failed = false;
6146 }
6147
6148 void *R_FrameData_Alloc(size_t size)
6149 {
6150         void *data;
6151
6152         // align to 16 byte boundary
6153         size = (size + 15) & ~15;
6154         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
6155         r_framedata_current += size;
6156
6157         // check overflow
6158         if (r_framedata_current > r_framedata_size)
6159                 r_framedata_failed = true;
6160
6161         // return NULL on everything after a failure
6162         if (r_framedata_failed)
6163                 return NULL;
6164
6165         return data;
6166 }
6167
6168 void *R_FrameData_Store(size_t size, void *data)
6169 {
6170         void *d = R_FrameData_Alloc(size);
6171         if (d)
6172                 memcpy(d, data, size);
6173         return d;
6174 }
6175
6176 //==================================================================================
6177
6178 // LordHavoc: animcache originally written by Echon, rewritten since then
6179
6180 /**
6181  * Animation cache prevents re-generating mesh data for an animated model
6182  * multiple times in one frame for lighting, shadowing, reflections, etc.
6183  */
6184
6185 void R_AnimCache_Free(void)
6186 {
6187 }
6188
6189 void R_AnimCache_ClearCache(void)
6190 {
6191         int i;
6192         entity_render_t *ent;
6193
6194         for (i = 0;i < r_refdef.scene.numentities;i++)
6195         {
6196                 ent = r_refdef.scene.entities[i];
6197                 ent->animcache_vertex3f = NULL;
6198                 ent->animcache_normal3f = NULL;
6199                 ent->animcache_svector3f = NULL;
6200                 ent->animcache_tvector3f = NULL;
6201         }
6202 }
6203
6204 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6205 {
6206         dp_model_t *model = ent->model;
6207         int numvertices;
6208         // see if it's already cached this frame
6209         if (ent->animcache_vertex3f)
6210         {
6211                 // add normals/tangents if needed
6212                 if (wantnormals || wanttangents)
6213                 {
6214                         if (ent->animcache_normal3f)
6215                                 wantnormals = false;
6216                         if (ent->animcache_svector3f)
6217                                 wanttangents = false;
6218                         if (wantnormals || wanttangents)
6219                         {
6220                                 numvertices = model->surfmesh.num_vertices;
6221                                 if (wantnormals)
6222                                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6223                                 if (wanttangents)
6224                                 {
6225                                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6226                                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6227                                 }
6228                                 if (!r_framedata_failed)
6229                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
6230                         }
6231                 }
6232         }
6233         else
6234         {
6235                 // see if this ent is worth caching
6236                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
6237                         return false;
6238                 // get some memory for this entity and generate mesh data
6239                 numvertices = model->surfmesh.num_vertices;
6240                 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6241                 if (wantnormals)
6242                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6243                 if (wanttangents)
6244                 {
6245                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6246                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6247                 }
6248                 if (!r_framedata_failed)
6249                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
6250         }
6251         return !r_framedata_failed;
6252 }
6253
6254 void R_AnimCache_CacheVisibleEntities(void)
6255 {
6256         int i;
6257         qboolean wantnormals = !r_showsurfaces.integer;
6258         qboolean wanttangents = !r_showsurfaces.integer;
6259
6260         switch(vid.renderpath)
6261         {
6262         case RENDERPATH_GL20:
6263         case RENDERPATH_CGGL:
6264                 break;
6265         case RENDERPATH_GL13:
6266         case RENDERPATH_GL11:
6267                 wanttangents = false;
6268                 break;
6269         }
6270
6271         // TODO: thread this
6272         // NOTE: R_PrepareRTLights() also caches entities
6273
6274         for (i = 0;i < r_refdef.scene.numentities;i++)
6275                 if (r_refdef.viewcache.entityvisible[i])
6276                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
6277
6278         if (r_shadows.integer)
6279                 for (i = 0;i < r_refdef.scene.numentities;i++)
6280                         if (!r_refdef.viewcache.entityvisible[i])
6281                                 R_AnimCache_GetEntity(r_refdef.scene.entities[i], false, false);
6282 }
6283
6284 //==================================================================================
6285
6286 static void R_View_UpdateEntityLighting (void)
6287 {
6288         int i;
6289         entity_render_t *ent;
6290         vec3_t tempdiffusenormal, avg;
6291         vec_t f, fa, fd, fdd;
6292
6293         for (i = 0;i < r_refdef.scene.numentities;i++)
6294         {
6295                 ent = r_refdef.scene.entities[i];
6296
6297                 // skip unseen models
6298                 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
6299                         continue;
6300
6301                 // skip bsp models
6302                 if (ent->model && ent->model->brush.num_leafs)
6303                 {
6304                         // TODO: use modellight for r_ambient settings on world?
6305                         VectorSet(ent->modellight_ambient, 0, 0, 0);
6306                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
6307                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
6308                         continue;
6309                 }
6310
6311                 // fetch the lighting from the worldmodel data
6312                 VectorClear(ent->modellight_ambient);
6313                 VectorClear(ent->modellight_diffuse);
6314                 VectorClear(tempdiffusenormal);
6315                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
6316                 {
6317                         vec3_t org;
6318                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6319                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
6320                         if(ent->flags & RENDER_EQUALIZE)
6321                         {
6322                                 // first fix up ambient lighting...
6323                                 if(r_equalize_entities_minambient.value > 0)
6324                                 {
6325                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
6326                                         if(fd > 0)
6327                                         {
6328                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
6329                                                 if(fa < r_equalize_entities_minambient.value * fd)
6330                                                 {
6331                                                         // solve:
6332                                                         //   fa'/fd' = minambient
6333                                                         //   fa'+0.25*fd' = fa+0.25*fd
6334                                                         //   ...
6335                                                         //   fa' = fd' * minambient
6336                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
6337                                                         //   ...
6338                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
6339                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
6340                                                         //   ...
6341                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
6342                                                         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
6343                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
6344                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6345                                                 }
6346                                         }
6347                                 }
6348
6349                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
6350                                 {
6351                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
6352                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
6353                                         if(f > 0)
6354                                         {
6355                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
6356                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
6357                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6358                                         }
6359                                 }
6360                         }
6361                 }
6362                 else // highly rare
6363                         VectorSet(ent->modellight_ambient, 1, 1, 1);
6364
6365                 // move the light direction into modelspace coordinates for lighting code
6366                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
6367                 if(VectorLength2(ent->modellight_lightdir) == 0)
6368                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
6369                 VectorNormalize(ent->modellight_lightdir);
6370         }
6371 }
6372
6373 #define MAX_LINEOFSIGHTTRACES 64
6374
6375 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
6376 {
6377         int i;
6378         vec3_t boxmins, boxmaxs;
6379         vec3_t start;
6380         vec3_t end;
6381         dp_model_t *model = r_refdef.scene.worldmodel;
6382
6383         if (!model || !model->brush.TraceLineOfSight)
6384                 return true;
6385
6386         // expand the box a little
6387         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
6388         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
6389         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
6390         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
6391         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
6392         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
6393
6394         // try center
6395         VectorCopy(eye, start);
6396         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
6397         if (model->brush.TraceLineOfSight(model, start, end))
6398                 return true;
6399
6400         // try various random positions
6401         for (i = 0;i < numsamples;i++)
6402         {
6403                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
6404                 if (model->brush.TraceLineOfSight(model, start, end))
6405                         return true;
6406         }
6407
6408         return false;
6409 }
6410
6411
6412 static void R_View_UpdateEntityVisible (void)
6413 {
6414         int i;
6415         int renderimask;
6416         int samples;
6417         entity_render_t *ent;
6418
6419         renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
6420         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
6421         {
6422                 // worldmodel can check visibility
6423                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
6424                 for (i = 0;i < r_refdef.scene.numentities;i++)
6425                 {
6426                         ent = r_refdef.scene.entities[i];
6427                         if (!(ent->flags & renderimask))
6428                         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)))
6429                         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))
6430                                 r_refdef.viewcache.entityvisible[i] = true;
6431                 }
6432                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
6433                 {
6434                         for (i = 0;i < r_refdef.scene.numentities;i++)
6435                         {
6436                                 ent = r_refdef.scene.entities[i];
6437                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
6438                                 {
6439                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
6440                                         if (samples < 0)
6441                                                 continue; // temp entities do pvs only
6442                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
6443                                                 ent->last_trace_visibility = realtime;
6444                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
6445                                                 r_refdef.viewcache.entityvisible[i] = 0;
6446                                 }
6447                         }
6448                 }
6449         }
6450         else
6451         {
6452                 // no worldmodel or it can't check visibility
6453                 for (i = 0;i < r_refdef.scene.numentities;i++)
6454                 {
6455                         ent = r_refdef.scene.entities[i];
6456                         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));
6457                 }
6458         }
6459 }
6460
6461 /// only used if skyrendermasked, and normally returns false
6462 int R_DrawBrushModelsSky (void)
6463 {
6464         int i, sky;
6465         entity_render_t *ent;
6466
6467         sky = false;
6468         for (i = 0;i < r_refdef.scene.numentities;i++)
6469         {
6470                 if (!r_refdef.viewcache.entityvisible[i])
6471                         continue;
6472                 ent = r_refdef.scene.entities[i];
6473                 if (!ent->model || !ent->model->DrawSky)
6474                         continue;
6475                 ent->model->DrawSky(ent);
6476                 sky = true;
6477         }
6478         return sky;
6479 }
6480
6481 static void R_DrawNoModel(entity_render_t *ent);
6482 static void R_DrawModels(void)
6483 {
6484         int i;
6485         entity_render_t *ent;
6486
6487         for (i = 0;i < r_refdef.scene.numentities;i++)
6488         {
6489                 if (!r_refdef.viewcache.entityvisible[i])
6490                         continue;
6491                 ent = r_refdef.scene.entities[i];
6492                 r_refdef.stats.entities++;
6493                 if (ent->model && ent->model->Draw != NULL)
6494                         ent->model->Draw(ent);
6495                 else
6496                         R_DrawNoModel(ent);
6497         }
6498 }
6499
6500 static void R_DrawModelsDepth(void)
6501 {
6502         int i;
6503         entity_render_t *ent;
6504
6505         for (i = 0;i < r_refdef.scene.numentities;i++)
6506         {
6507                 if (!r_refdef.viewcache.entityvisible[i])
6508                         continue;
6509                 ent = r_refdef.scene.entities[i];
6510                 if (ent->model && ent->model->DrawDepth != NULL)
6511                         ent->model->DrawDepth(ent);
6512         }
6513 }
6514
6515 static void R_DrawModelsDebug(void)
6516 {
6517         int i;
6518         entity_render_t *ent;
6519
6520         for (i = 0;i < r_refdef.scene.numentities;i++)
6521         {
6522                 if (!r_refdef.viewcache.entityvisible[i])
6523                         continue;
6524                 ent = r_refdef.scene.entities[i];
6525                 if (ent->model && ent->model->DrawDebug != NULL)
6526                         ent->model->DrawDebug(ent);
6527         }
6528 }
6529
6530 static void R_DrawModelsAddWaterPlanes(void)
6531 {
6532         int i;
6533         entity_render_t *ent;
6534
6535         for (i = 0;i < r_refdef.scene.numentities;i++)
6536         {
6537                 if (!r_refdef.viewcache.entityvisible[i])
6538                         continue;
6539                 ent = r_refdef.scene.entities[i];
6540                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
6541                         ent->model->DrawAddWaterPlanes(ent);
6542         }
6543 }
6544
6545 static void R_View_SetFrustum(void)
6546 {
6547         int i;
6548         double slopex, slopey;
6549         vec3_t forward, left, up, origin;
6550
6551         // we can't trust r_refdef.view.forward and friends in reflected scenes
6552         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
6553
6554 #if 0
6555         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
6556         r_refdef.view.frustum[0].normal[1] = 0 - 0;
6557         r_refdef.view.frustum[0].normal[2] = -1 - 0;
6558         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
6559         r_refdef.view.frustum[1].normal[1] = 0 + 0;
6560         r_refdef.view.frustum[1].normal[2] = -1 + 0;
6561         r_refdef.view.frustum[2].normal[0] = 0 - 0;
6562         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
6563         r_refdef.view.frustum[2].normal[2] = -1 - 0;
6564         r_refdef.view.frustum[3].normal[0] = 0 + 0;
6565         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
6566         r_refdef.view.frustum[3].normal[2] = -1 + 0;
6567 #endif
6568
6569 #if 0
6570         zNear = r_refdef.nearclip;
6571         nudge = 1.0 - 1.0 / (1<<23);
6572         r_refdef.view.frustum[4].normal[0] = 0 - 0;
6573         r_refdef.view.frustum[4].normal[1] = 0 - 0;
6574         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
6575         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
6576         r_refdef.view.frustum[5].normal[0] = 0 + 0;
6577         r_refdef.view.frustum[5].normal[1] = 0 + 0;
6578         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
6579         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
6580 #endif
6581
6582
6583
6584 #if 0
6585         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
6586         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
6587         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
6588         r_refdef.view.frustum[0].dist = m[15] - m[12];
6589
6590         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
6591         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
6592         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
6593         r_refdef.view.frustum[1].dist = m[15] + m[12];
6594
6595         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
6596         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
6597         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
6598         r_refdef.view.frustum[2].dist = m[15] - m[13];
6599
6600         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
6601         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
6602         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
6603         r_refdef.view.frustum[3].dist = m[15] + m[13];
6604
6605         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
6606         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
6607         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
6608         r_refdef.view.frustum[4].dist = m[15] - m[14];
6609
6610         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
6611         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
6612         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
6613         r_refdef.view.frustum[5].dist = m[15] + m[14];
6614 #endif
6615
6616         if (r_refdef.view.useperspective)
6617         {
6618                 slopex = 1.0 / r_refdef.view.frustum_x;
6619                 slopey = 1.0 / r_refdef.view.frustum_y;
6620                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
6621                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
6622                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
6623                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
6624                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6625
6626                 // Leaving those out was a mistake, those were in the old code, and they
6627                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
6628                 // I couldn't reproduce it after adding those normalizations. --blub
6629                 VectorNormalize(r_refdef.view.frustum[0].normal);
6630                 VectorNormalize(r_refdef.view.frustum[1].normal);
6631                 VectorNormalize(r_refdef.view.frustum[2].normal);
6632                 VectorNormalize(r_refdef.view.frustum[3].normal);
6633
6634                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
6635                 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]);
6636                 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]);
6637                 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]);
6638                 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]);
6639
6640                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
6641                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
6642                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
6643                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
6644                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6645         }
6646         else
6647         {
6648                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
6649                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
6650                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
6651                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
6652                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6653                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
6654                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
6655                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
6656                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
6657                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6658         }
6659         r_refdef.view.numfrustumplanes = 5;
6660
6661         if (r_refdef.view.useclipplane)
6662         {
6663                 r_refdef.view.numfrustumplanes = 6;
6664                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
6665         }
6666
6667         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6668                 PlaneClassify(r_refdef.view.frustum + i);
6669
6670         // LordHavoc: note to all quake engine coders, Quake had a special case
6671         // for 90 degrees which assumed a square view (wrong), so I removed it,
6672         // Quake2 has it disabled as well.
6673
6674         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
6675         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
6676         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
6677         //PlaneClassify(&frustum[0]);
6678
6679         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
6680         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
6681         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
6682         //PlaneClassify(&frustum[1]);
6683
6684         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
6685         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
6686         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
6687         //PlaneClassify(&frustum[2]);
6688
6689         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
6690         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
6691         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
6692         //PlaneClassify(&frustum[3]);
6693
6694         // nearclip plane
6695         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
6696         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
6697         //PlaneClassify(&frustum[4]);
6698 }
6699
6700 void R_View_Update(void)
6701 {
6702         R_Main_ResizeViewCache();
6703         R_View_SetFrustum();
6704         R_View_WorldVisibility(r_refdef.view.useclipplane);
6705         R_View_UpdateEntityVisible();
6706         R_View_UpdateEntityLighting();
6707 }
6708
6709 void R_SetupView(qboolean allowwaterclippingplane)
6710 {
6711         const float *customclipplane = NULL;
6712         float plane[4];
6713         if (r_refdef.view.useclipplane && allowwaterclippingplane)
6714         {
6715                 // LordHavoc: couldn't figure out how to make this approach the
6716                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
6717                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
6718                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
6719                         dist = r_refdef.view.clipplane.dist;
6720                 plane[0] = r_refdef.view.clipplane.normal[0];
6721                 plane[1] = r_refdef.view.clipplane.normal[1];
6722                 plane[2] = r_refdef.view.clipplane.normal[2];
6723                 plane[3] = dist;
6724                 customclipplane = plane;
6725         }
6726
6727         if (!r_refdef.view.useperspective)
6728                 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);
6729         else if (vid.stencil && r_useinfinitefarclip.integer)
6730                 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);
6731         else
6732                 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);
6733         R_SetViewport(&r_refdef.view.viewport);
6734 }
6735
6736 void R_EntityMatrix(const matrix4x4_t *matrix)
6737 {
6738         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
6739         {
6740                 gl_modelmatrixchanged = false;
6741                 gl_modelmatrix = *matrix;
6742                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
6743                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
6744                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
6745                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
6746                 CHECKGLERROR
6747                 switch(vid.renderpath)
6748                 {
6749                 case RENDERPATH_GL20:
6750                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
6751                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
6752                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6753                         break;
6754                 case RENDERPATH_CGGL:
6755 #ifdef SUPPORTCG
6756                         CHECKCGERROR
6757                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
6758                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
6759                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6760 #endif
6761                         break;
6762                 case RENDERPATH_GL13:
6763                 case RENDERPATH_GL11:
6764                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6765                         break;
6766                 }
6767         }
6768 }
6769
6770 void R_ResetViewRendering2D(void)
6771 {
6772         r_viewport_t viewport;
6773         DrawQ_Finish();
6774
6775         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
6776         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);
6777         R_SetViewport(&viewport);
6778         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
6779         GL_Color(1, 1, 1, 1);
6780         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6781         GL_BlendFunc(GL_ONE, GL_ZERO);
6782         GL_AlphaTest(false);
6783         GL_ScissorTest(false);
6784         GL_DepthMask(false);
6785         GL_DepthRange(0, 1);
6786         GL_DepthTest(false);
6787         R_EntityMatrix(&identitymatrix);
6788         R_Mesh_ResetTextureState();
6789         GL_PolygonOffset(0, 0);
6790         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
6791         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6792         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
6793         qglStencilMask(~0);CHECKGLERROR
6794         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
6795         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
6796         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
6797 }
6798
6799 void R_ResetViewRendering3D(void)
6800 {
6801         DrawQ_Finish();
6802
6803         R_SetupView(true);
6804         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6805         GL_Color(1, 1, 1, 1);
6806         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6807         GL_BlendFunc(GL_ONE, GL_ZERO);
6808         GL_AlphaTest(false);
6809         GL_ScissorTest(true);
6810         GL_DepthMask(true);
6811         GL_DepthRange(0, 1);
6812         GL_DepthTest(true);
6813         R_EntityMatrix(&identitymatrix);
6814         R_Mesh_ResetTextureState();
6815         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6816         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
6817         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6818         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
6819         qglStencilMask(~0);CHECKGLERROR
6820         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
6821         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
6822         GL_CullFace(r_refdef.view.cullface_back);
6823 }
6824
6825 void R_RenderScene(void);
6826 void R_RenderWaterPlanes(void);
6827
6828 static void R_Water_StartFrame(void)
6829 {
6830         int i;
6831         int waterwidth, waterheight, texturewidth, textureheight;
6832         r_waterstate_waterplane_t *p;
6833
6834         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
6835                 return;
6836
6837         switch(vid.renderpath)
6838         {
6839         case RENDERPATH_GL20:
6840         case RENDERPATH_CGGL:
6841                 break;
6842         case RENDERPATH_GL13:
6843         case RENDERPATH_GL11:
6844                 return;
6845         }
6846
6847         // set waterwidth and waterheight to the water resolution that will be
6848         // used (often less than the screen resolution for faster rendering)
6849         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
6850         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
6851
6852         // calculate desired texture sizes
6853         // can't use water if the card does not support the texture size
6854         if (!r_water.integer || r_showsurfaces.integer)
6855                 texturewidth = textureheight = waterwidth = waterheight = 0;
6856         else if (vid.support.arb_texture_non_power_of_two)
6857         {
6858                 texturewidth = waterwidth;
6859                 textureheight = waterheight;
6860         }
6861         else
6862         {
6863                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
6864                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
6865         }
6866
6867         // allocate textures as needed
6868         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
6869         {
6870                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
6871                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
6872                 {
6873                         if (p->texture_refraction)
6874                                 R_FreeTexture(p->texture_refraction);
6875                         p->texture_refraction = NULL;
6876                         if (p->texture_reflection)
6877                                 R_FreeTexture(p->texture_reflection);
6878                         p->texture_reflection = NULL;
6879                 }
6880                 memset(&r_waterstate, 0, sizeof(r_waterstate));
6881                 r_waterstate.texturewidth = texturewidth;
6882                 r_waterstate.textureheight = textureheight;
6883         }
6884
6885         if (r_waterstate.texturewidth)
6886         {
6887                 r_waterstate.enabled = true;
6888
6889                 // when doing a reduced render (HDR) we want to use a smaller area
6890                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
6891                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
6892
6893                 // set up variables that will be used in shader setup
6894                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
6895                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
6896                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
6897                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
6898         }
6899
6900         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
6901         r_waterstate.numwaterplanes = 0;
6902 }
6903
6904 void R_Water_AddWaterPlane(msurface_t *surface)
6905 {
6906         int triangleindex, planeindex;
6907         const int *e;
6908         vec3_t vert[3];
6909         vec3_t normal;
6910         vec3_t center;
6911         mplane_t plane;
6912         r_waterstate_waterplane_t *p;
6913         texture_t *t = R_GetCurrentTexture(surface->texture);
6914         // just use the first triangle with a valid normal for any decisions
6915         VectorClear(normal);
6916         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
6917         {
6918                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
6919                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
6920                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
6921                 TriangleNormal(vert[0], vert[1], vert[2], normal);
6922                 if (VectorLength2(normal) >= 0.001)
6923                         break;
6924         }
6925
6926         VectorCopy(normal, plane.normal);
6927         VectorNormalize(plane.normal);
6928         plane.dist = DotProduct(vert[0], plane.normal);
6929         PlaneClassify(&plane);
6930         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
6931         {
6932                 // skip backfaces (except if nocullface is set)
6933                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
6934                         return;
6935                 VectorNegate(plane.normal, plane.normal);
6936                 plane.dist *= -1;
6937                 PlaneClassify(&plane);
6938         }
6939
6940
6941         // find a matching plane if there is one
6942         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6943                 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
6944                         break;
6945         if (planeindex >= r_waterstate.maxwaterplanes)
6946                 return; // nothing we can do, out of planes
6947
6948         // if this triangle does not fit any known plane rendered this frame, add one
6949         if (planeindex >= r_waterstate.numwaterplanes)
6950         {
6951                 // store the new plane
6952                 r_waterstate.numwaterplanes++;
6953                 p->plane = plane;
6954                 // clear materialflags and pvs
6955                 p->materialflags = 0;
6956                 p->pvsvalid = false;
6957         }
6958         // merge this surface's materialflags into the waterplane
6959         p->materialflags |= t->currentmaterialflags;
6960         // merge this surface's PVS into the waterplane
6961         VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
6962         if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6963          && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6964         {
6965                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6966                 p->pvsvalid = true;
6967         }
6968 }
6969
6970 static void R_Water_ProcessPlanes(void)
6971 {
6972         r_refdef_view_t originalview;
6973         r_refdef_view_t myview;
6974         int planeindex;
6975         r_waterstate_waterplane_t *p;
6976
6977         originalview = r_refdef.view;
6978
6979         // make sure enough textures are allocated
6980         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6981         {
6982                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6983                 {
6984                         if (!p->texture_refraction)
6985                                 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);
6986                         if (!p->texture_refraction)
6987                                 goto error;
6988                 }
6989
6990                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6991                 {
6992                         if (!p->texture_reflection)
6993                                 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);
6994                         if (!p->texture_reflection)
6995                                 goto error;
6996                 }
6997         }
6998
6999         // render views
7000         r_refdef.view = originalview;
7001         r_refdef.view.showdebug = false;
7002         r_refdef.view.width = r_waterstate.waterwidth;
7003         r_refdef.view.height = r_waterstate.waterheight;
7004         r_refdef.view.useclipplane = true;
7005         myview = r_refdef.view;
7006         r_waterstate.renderingscene = true;
7007         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7008         {
7009                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7010                 {
7011                         r_refdef.view = myview;
7012                         // render reflected scene and copy into texture
7013                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
7014                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
7015                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
7016                         r_refdef.view.clipplane = p->plane;
7017                         // reverse the cullface settings for this render
7018                         r_refdef.view.cullface_front = GL_FRONT;
7019                         r_refdef.view.cullface_back = GL_BACK;
7020                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
7021                         {
7022                                 r_refdef.view.usecustompvs = true;
7023                                 if (p->pvsvalid)
7024                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7025                                 else
7026                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7027                         }
7028
7029                         R_ResetViewRendering3D();
7030                         R_ClearScreen(r_refdef.fogenabled);
7031                         R_View_Update();
7032                         R_RenderScene();
7033
7034                         R_Mesh_CopyToTexture(p->texture_reflection, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7035                 }
7036
7037                 // render the normal view scene and copy into texture
7038                 // (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)
7039                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7040                 {
7041                         r_refdef.view = myview;
7042                         r_refdef.view.clipplane = p->plane;
7043                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
7044                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
7045                         PlaneClassify(&r_refdef.view.clipplane);
7046
7047                         R_ResetViewRendering3D();
7048                         R_ClearScreen(r_refdef.fogenabled);
7049                         R_View_Update();
7050                         R_RenderScene();
7051
7052                         R_Mesh_CopyToTexture(p->texture_refraction, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7053                 }
7054
7055         }
7056         r_waterstate.renderingscene = false;
7057         r_refdef.view = originalview;
7058         R_ResetViewRendering3D();
7059         R_ClearScreen(r_refdef.fogenabled);
7060         R_View_Update();
7061         return;
7062 error:
7063         r_refdef.view = originalview;
7064         r_waterstate.renderingscene = false;
7065         Cvar_SetValueQuick(&r_water, 0);
7066         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
7067         return;
7068 }
7069
7070 void R_Bloom_StartFrame(void)
7071 {
7072         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
7073
7074         switch(vid.renderpath)
7075         {
7076         case RENDERPATH_GL20:
7077         case RENDERPATH_CGGL:
7078                 break;
7079         case RENDERPATH_GL13:
7080         case RENDERPATH_GL11:
7081                 return;
7082         }
7083
7084         // set bloomwidth and bloomheight to the bloom resolution that will be
7085         // used (often less than the screen resolution for faster rendering)
7086         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
7087         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
7088         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
7089         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
7090         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
7091
7092         // calculate desired texture sizes
7093         if (vid.support.arb_texture_non_power_of_two)
7094         {
7095                 screentexturewidth = r_refdef.view.width;
7096                 screentextureheight = r_refdef.view.height;
7097                 bloomtexturewidth = r_bloomstate.bloomwidth;
7098                 bloomtextureheight = r_bloomstate.bloomheight;
7099         }
7100         else
7101         {
7102                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
7103                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
7104                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
7105                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
7106         }
7107
7108         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))
7109         {
7110                 Cvar_SetValueQuick(&r_hdr, 0);
7111                 Cvar_SetValueQuick(&r_bloom, 0);
7112                 Cvar_SetValueQuick(&r_motionblur, 0);
7113                 Cvar_SetValueQuick(&r_damageblur, 0);
7114         }
7115
7116         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)))
7117                 screentexturewidth = screentextureheight = 0;
7118         if (!r_hdr.integer && !r_bloom.integer)
7119                 bloomtexturewidth = bloomtextureheight = 0;
7120
7121         // allocate textures as needed
7122         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
7123         {
7124                 if (r_bloomstate.texture_screen)
7125                         R_FreeTexture(r_bloomstate.texture_screen);
7126                 r_bloomstate.texture_screen = NULL;
7127                 r_bloomstate.screentexturewidth = screentexturewidth;
7128                 r_bloomstate.screentextureheight = screentextureheight;
7129                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
7130                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
7131         }
7132         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
7133         {
7134                 if (r_bloomstate.texture_bloom)
7135                         R_FreeTexture(r_bloomstate.texture_bloom);
7136                 r_bloomstate.texture_bloom = NULL;
7137                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
7138                 r_bloomstate.bloomtextureheight = bloomtextureheight;
7139                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
7140                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7141         }
7142
7143         // when doing a reduced render (HDR) we want to use a smaller area
7144         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
7145         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
7146         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
7147         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
7148         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
7149
7150         // set up a texcoord array for the full resolution screen image
7151         // (we have to keep this around to copy back during final render)
7152         r_bloomstate.screentexcoord2f[0] = 0;
7153         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7154         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7155         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7156         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7157         r_bloomstate.screentexcoord2f[5] = 0;
7158         r_bloomstate.screentexcoord2f[6] = 0;
7159         r_bloomstate.screentexcoord2f[7] = 0;
7160
7161         // set up a texcoord array for the reduced resolution bloom image
7162         // (which will be additive blended over the screen image)
7163         r_bloomstate.bloomtexcoord2f[0] = 0;
7164         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7165         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7166         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7167         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7168         r_bloomstate.bloomtexcoord2f[5] = 0;
7169         r_bloomstate.bloomtexcoord2f[6] = 0;
7170         r_bloomstate.bloomtexcoord2f[7] = 0;
7171
7172         if (r_hdr.integer || r_bloom.integer)
7173         {
7174                 r_bloomstate.enabled = true;
7175                 r_bloomstate.hdr = r_hdr.integer != 0;
7176         }
7177
7178         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);
7179 }
7180
7181 void R_Bloom_CopyBloomTexture(float colorscale)
7182 {
7183         r_refdef.stats.bloom++;
7184
7185         // scale down screen texture to the bloom texture size
7186         CHECKGLERROR
7187         R_SetViewport(&r_bloomstate.viewport);
7188         GL_BlendFunc(GL_ONE, GL_ZERO);
7189         GL_Color(colorscale, colorscale, colorscale, 1);
7190         // TODO: optimize with multitexture or GLSL
7191         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7192         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7193         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7194         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7195
7196         // we now have a bloom image in the framebuffer
7197         // copy it into the bloom image texture for later processing
7198         R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
7199         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7200 }
7201
7202 void R_Bloom_CopyHDRTexture(void)
7203 {
7204         R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7205         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7206 }
7207
7208 void R_Bloom_MakeTexture(void)
7209 {
7210         int x, range, dir;
7211         float xoffset, yoffset, r, brighten;
7212
7213         r_refdef.stats.bloom++;
7214
7215         R_ResetViewRendering2D();
7216         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7217         R_Mesh_ColorPointer(NULL, 0, 0);
7218
7219         // we have a bloom image in the framebuffer
7220         CHECKGLERROR
7221         R_SetViewport(&r_bloomstate.viewport);
7222
7223         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
7224         {
7225                 x *= 2;
7226                 r = bound(0, r_bloom_colorexponent.value / x, 1);
7227                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7228                 GL_Color(r, r, r, 1);
7229                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7230                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7231                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7232                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7233
7234                 // copy the vertically blurred bloom view to a texture
7235                 GL_ActiveTexture(0);
7236                 CHECKGLERROR
7237                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
7238                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7239         }
7240
7241         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
7242         brighten = r_bloom_brighten.value;
7243         if (r_hdr.integer)
7244                 brighten *= r_hdr_range.value;
7245         brighten = sqrt(brighten);
7246         if(range >= 1)
7247                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
7248         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7249         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
7250
7251         for (dir = 0;dir < 2;dir++)
7252         {
7253                 // blend on at multiple vertical offsets to achieve a vertical blur
7254                 // TODO: do offset blends using GLSL
7255                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
7256                 GL_BlendFunc(GL_ONE, GL_ZERO);
7257                 for (x = -range;x <= range;x++)
7258                 {
7259                         if (!dir){xoffset = 0;yoffset = x;}
7260                         else {xoffset = x;yoffset = 0;}
7261                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
7262                         yoffset /= (float)r_bloomstate.bloomtextureheight;
7263                         // compute a texcoord array with the specified x and y offset
7264                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
7265                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7266                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7267                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7268                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7269                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
7270                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
7271                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
7272                         // this r value looks like a 'dot' particle, fading sharply to
7273                         // black at the edges
7274                         // (probably not realistic but looks good enough)
7275                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
7276                         //r = brighten/(range*2+1);
7277                         r = brighten / (range * 2 + 1);
7278                         if(range >= 1)
7279                                 r *= (1 - x*x/(float)(range*range));
7280                         GL_Color(r, r, r, 1);
7281                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7282                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7283                         GL_BlendFunc(GL_ONE, GL_ONE);
7284                 }
7285
7286                 // copy the vertically blurred bloom view to a texture
7287                 GL_ActiveTexture(0);
7288                 CHECKGLERROR
7289                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
7290                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7291         }
7292
7293         // apply subtract last
7294         // (just like it would be in a GLSL shader)
7295         if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
7296         {
7297                 GL_BlendFunc(GL_ONE, GL_ZERO);
7298                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7299                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7300                 GL_Color(1, 1, 1, 1);
7301                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7302                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7303
7304                 GL_BlendFunc(GL_ONE, GL_ONE);
7305                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
7306                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7307                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7308                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
7309                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7310                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7311                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
7312
7313                 // copy the darkened bloom view to a texture
7314                 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
7315                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7316         }
7317 }
7318
7319 void R_HDR_RenderBloomTexture(void)
7320 {
7321         int oldwidth, oldheight;
7322         float oldcolorscale;
7323
7324         oldcolorscale = r_refdef.view.colorscale;
7325         oldwidth = r_refdef.view.width;
7326         oldheight = r_refdef.view.height;
7327         r_refdef.view.width = r_bloomstate.bloomwidth;
7328         r_refdef.view.height = r_bloomstate.bloomheight;
7329
7330         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
7331         // TODO: add exposure compensation features
7332         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
7333
7334         r_refdef.view.showdebug = false;
7335         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
7336
7337         R_ResetViewRendering3D();
7338
7339         R_ClearScreen(r_refdef.fogenabled);
7340         if (r_timereport_active)
7341                 R_TimeReport("HDRclear");
7342
7343         R_View_Update();
7344         if (r_timereport_active)
7345                 R_TimeReport("visibility");
7346
7347         // only do secondary renders with HDR if r_hdr is 2 or higher
7348         r_waterstate.numwaterplanes = 0;
7349         if (r_waterstate.enabled && r_hdr.integer >= 2)
7350                 R_RenderWaterPlanes();
7351
7352         r_refdef.view.showdebug = true;
7353         R_RenderScene();
7354         r_waterstate.numwaterplanes = 0;
7355
7356         R_ResetViewRendering2D();
7357
7358         R_Bloom_CopyHDRTexture();
7359         R_Bloom_MakeTexture();
7360
7361         // restore the view settings
7362         r_refdef.view.width = oldwidth;
7363         r_refdef.view.height = oldheight;
7364         r_refdef.view.colorscale = oldcolorscale;
7365
7366         R_ResetViewRendering3D();
7367
7368         R_ClearScreen(r_refdef.fogenabled);
7369         if (r_timereport_active)
7370                 R_TimeReport("viewclear");
7371 }
7372
7373 static void R_BlendView(void)
7374 {
7375         unsigned int permutation;
7376         float uservecs[4][4];
7377
7378         switch (vid.renderpath)
7379         {
7380         case RENDERPATH_GL20:
7381         case RENDERPATH_CGGL:
7382                 permutation =
7383                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
7384                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
7385                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
7386                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
7387                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
7388
7389                 if (r_bloomstate.texture_screen)
7390                 {
7391                         // make sure the buffer is available
7392                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
7393
7394                         R_ResetViewRendering2D();
7395                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7396                         R_Mesh_ColorPointer(NULL, 0, 0);
7397
7398                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
7399                         {
7400                                 // declare variables
7401                                 float speed;
7402                                 static float avgspeed;
7403
7404                                 speed = VectorLength(cl.movement_velocity);
7405
7406                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
7407                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
7408
7409                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
7410                                 speed = bound(0, speed, 1);
7411                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
7412
7413                                 // calculate values into a standard alpha
7414                                 cl.motionbluralpha = 1 - exp(-
7415                                                 (
7416                                                  (r_motionblur.value * speed / 80)
7417                                                  +
7418                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
7419                                                 )
7420                                                 /
7421                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
7422                                            );
7423
7424                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
7425                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
7426                                 // apply the blur
7427                                 if (cl.motionbluralpha > 0)
7428                                 {
7429                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7430                                         GL_Color(1, 1, 1, cl.motionbluralpha);
7431                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7432                                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7433                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7434                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7435                                 }
7436                         }
7437
7438                         // copy view into the screen texture
7439                         R_Mesh_CopyToTexture(r_bloomstate.texture_screen, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7440                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7441                 }
7442                 else if (!r_bloomstate.texture_bloom)
7443                 {
7444                         // we may still have to do view tint...
7445                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7446                         {
7447                                 // apply a color tint to the whole view
7448                                 R_ResetViewRendering2D();
7449                                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7450                                 R_Mesh_ColorPointer(NULL, 0, 0);
7451                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7452                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7453                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7454                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7455                         }
7456                         break; // no screen processing, no bloom, skip it
7457                 }
7458
7459                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
7460                 {
7461                         // render simple bloom effect
7462                         // copy the screen and shrink it and darken it for the bloom process
7463                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
7464                         // make the bloom texture
7465                         R_Bloom_MakeTexture();
7466                 }
7467
7468 #if _MSC_VER >= 1400
7469 #define sscanf sscanf_s
7470 #endif
7471                 memset(uservecs, 0, sizeof(uservecs));
7472                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
7473                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
7474                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
7475                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
7476
7477                 R_ResetViewRendering2D();
7478                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7479                 R_Mesh_ColorPointer(NULL, 0, 0);
7480                 GL_Color(1, 1, 1, 1);
7481                 GL_BlendFunc(GL_ONE, GL_ZERO);
7482                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7483                 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7484
7485                 switch(vid.renderpath)
7486                 {
7487                 case RENDERPATH_GL20:
7488                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
7489                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
7490                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
7491                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
7492                         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]);
7493                         if (r_glsl_permutation->loc_ClientTime         >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime        , cl.time);
7494                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
7495                         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]);
7496                         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]);
7497                         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]);
7498                         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]);
7499                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
7500                         break;
7501                 case RENDERPATH_CGGL:
7502 #ifdef SUPPORTCG
7503                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
7504                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
7505                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
7506                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
7507                         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
7508                         if (r_cg_permutation->fp_ClientTime        ) cgGLSetParameter1f(     r_cg_permutation->fp_ClientTime        , cl.time);CHECKCGERROR
7509                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
7510                         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
7511                         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
7512                         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
7513                         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
7514                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
7515 #endif
7516                         break;
7517                 default:
7518                         break;
7519                 }
7520                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7521                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7522                 break;
7523         case RENDERPATH_GL13:
7524         case RENDERPATH_GL11:
7525                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7526                 {
7527                         // apply a color tint to the whole view
7528                         R_ResetViewRendering2D();
7529                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7530                         R_Mesh_ColorPointer(NULL, 0, 0);
7531                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7532                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7533                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7534                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7535                 }
7536                 break;
7537         }
7538 }
7539
7540 matrix4x4_t r_waterscrollmatrix;
7541
7542 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
7543 {
7544         if (r_refdef.fog_density)
7545         {
7546                 r_refdef.fogcolor[0] = r_refdef.fog_red;
7547                 r_refdef.fogcolor[1] = r_refdef.fog_green;
7548                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7549
7550                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7551                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7552                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7553                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7554
7555                 {
7556                         vec3_t fogvec;
7557                         VectorCopy(r_refdef.fogcolor, fogvec);
7558                         //   color.rgb *= ContrastBoost * SceneBrightness;
7559                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7560                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7561                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7562                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7563                 }
7564         }
7565 }
7566
7567 void R_UpdateVariables(void)
7568 {
7569         R_Textures_Frame();
7570
7571         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7572
7573         r_refdef.farclip = r_farclip_base.value;
7574         if (r_refdef.scene.worldmodel)
7575                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7576         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7577
7578         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7579                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7580         r_refdef.polygonfactor = 0;
7581         r_refdef.polygonoffset = 0;
7582         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7583         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7584
7585         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7586         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7587         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
7588         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7589         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7590         if (r_showsurfaces.integer)
7591         {
7592                 r_refdef.scene.rtworld = false;
7593                 r_refdef.scene.rtworldshadows = false;
7594                 r_refdef.scene.rtdlight = false;
7595                 r_refdef.scene.rtdlightshadows = false;
7596                 r_refdef.lightmapintensity = 0;
7597         }
7598
7599         if (gamemode == GAME_NEHAHRA)
7600         {
7601                 if (gl_fogenable.integer)
7602                 {
7603                         r_refdef.oldgl_fogenable = true;
7604                         r_refdef.fog_density = gl_fogdensity.value;
7605                         r_refdef.fog_red = gl_fogred.value;
7606                         r_refdef.fog_green = gl_foggreen.value;
7607                         r_refdef.fog_blue = gl_fogblue.value;
7608                         r_refdef.fog_alpha = 1;
7609                         r_refdef.fog_start = 0;
7610                         r_refdef.fog_end = gl_skyclip.value;
7611                         r_refdef.fog_height = 1<<30;
7612                         r_refdef.fog_fadedepth = 128;
7613                 }
7614                 else if (r_refdef.oldgl_fogenable)
7615                 {
7616                         r_refdef.oldgl_fogenable = false;
7617                         r_refdef.fog_density = 0;
7618                         r_refdef.fog_red = 0;
7619                         r_refdef.fog_green = 0;
7620                         r_refdef.fog_blue = 0;
7621                         r_refdef.fog_alpha = 0;
7622                         r_refdef.fog_start = 0;
7623                         r_refdef.fog_end = 0;
7624                         r_refdef.fog_height = 1<<30;
7625                         r_refdef.fog_fadedepth = 128;
7626                 }
7627         }
7628
7629         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7630         r_refdef.fog_start = max(0, r_refdef.fog_start);
7631         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7632
7633         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
7634
7635         if (r_refdef.fog_density && r_drawfog.integer)
7636         {
7637                 r_refdef.fogenabled = true;
7638                 // this is the point where the fog reaches 0.9986 alpha, which we
7639                 // consider a good enough cutoff point for the texture
7640                 // (0.9986 * 256 == 255.6)
7641                 if (r_fog_exp2.integer)
7642                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7643                 else
7644                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7645                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7646                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7647                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7648                 // fog color was already set
7649                 // update the fog texture
7650                 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)
7651                         R_BuildFogTexture();
7652         }
7653         else
7654                 r_refdef.fogenabled = false;
7655
7656         switch(vid.renderpath)
7657         {
7658         case RENDERPATH_GL20:
7659         case RENDERPATH_CGGL:
7660                 if(v_glslgamma.integer && !vid_gammatables_trivial)
7661                 {
7662                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7663                         {
7664                                 // build GLSL gamma texture
7665 #define RAMPWIDTH 256
7666                                 unsigned short ramp[RAMPWIDTH * 3];
7667                                 unsigned char rampbgr[RAMPWIDTH][4];
7668                                 int i;
7669
7670                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7671
7672                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7673                                 for(i = 0; i < RAMPWIDTH; ++i)
7674                                 {
7675                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7676                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7677                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7678                                         rampbgr[i][3] = 0;
7679                                 }
7680                                 if (r_texture_gammaramps)
7681                                 {
7682                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
7683                                 }
7684                                 else
7685                                 {
7686                                         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);
7687                                 }
7688                         }
7689                 }
7690                 else
7691                 {
7692                         // remove GLSL gamma texture
7693                 }
7694                 break;
7695         case RENDERPATH_GL13:
7696         case RENDERPATH_GL11:
7697                 break;
7698         }
7699 }
7700
7701 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7702 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7703 /*
7704 ================
7705 R_SelectScene
7706 ================
7707 */
7708 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7709         if( scenetype != r_currentscenetype ) {
7710                 // store the old scenetype
7711                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7712                 r_currentscenetype = scenetype;
7713                 // move in the new scene
7714                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7715         }
7716 }
7717
7718 /*
7719 ================
7720 R_GetScenePointer
7721 ================
7722 */
7723 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7724 {
7725         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7726         if( scenetype == r_currentscenetype ) {
7727                 return &r_refdef.scene;
7728         } else {
7729                 return &r_scenes_store[ scenetype ];
7730         }
7731 }
7732
7733 /*
7734 ================
7735 R_RenderView
7736 ================
7737 */
7738 void R_RenderView(void)
7739 {
7740         if (r_timereport_active)
7741                 R_TimeReport("start");
7742         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7743
7744         if (!r_drawentities.integer)
7745                 r_refdef.scene.numentities = 0;
7746
7747         R_AnimCache_ClearCache();
7748         R_FrameData_NewFrame();
7749
7750         if (r_refdef.view.isoverlay)
7751         {
7752                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7753                 GL_Clear( GL_DEPTH_BUFFER_BIT );
7754                 R_TimeReport("depthclear");
7755
7756                 r_refdef.view.showdebug = false;
7757
7758                 r_waterstate.enabled = false;
7759                 r_waterstate.numwaterplanes = 0;
7760
7761                 R_RenderScene();
7762
7763                 CHECKGLERROR
7764                 return;
7765         }
7766
7767         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
7768                 return; //Host_Error ("R_RenderView: NULL worldmodel");
7769
7770         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
7771
7772         // break apart the view matrix into vectors for various purposes
7773         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
7774         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
7775         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
7776         VectorNegate(r_refdef.view.left, r_refdef.view.right);
7777         // make an inverted copy of the view matrix for tracking sprites
7778         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
7779
7780         R_Shadow_UpdateWorldLightSelection();
7781
7782         R_Bloom_StartFrame();
7783         R_Water_StartFrame();
7784
7785         CHECKGLERROR
7786         if (r_timereport_active)
7787                 R_TimeReport("viewsetup");
7788
7789         R_ResetViewRendering3D();
7790
7791         if (r_refdef.view.clear || r_refdef.fogenabled)
7792         {
7793                 R_ClearScreen(r_refdef.fogenabled);
7794                 if (r_timereport_active)
7795                         R_TimeReport("viewclear");
7796         }
7797         r_refdef.view.clear = true;
7798
7799         // this produces a bloom texture to be used in R_BlendView() later
7800         if (r_hdr.integer && r_bloomstate.bloomwidth)
7801                 R_HDR_RenderBloomTexture();
7802
7803         r_refdef.view.showdebug = true;
7804
7805         R_View_Update();
7806         if (r_timereport_active)
7807                 R_TimeReport("visibility");
7808
7809         r_waterstate.numwaterplanes = 0;
7810         if (r_waterstate.enabled)
7811                 R_RenderWaterPlanes();
7812
7813         R_RenderScene();
7814         r_waterstate.numwaterplanes = 0;
7815
7816         R_BlendView();
7817         if (r_timereport_active)
7818                 R_TimeReport("blendview");
7819
7820         GL_Scissor(0, 0, vid.width, vid.height);
7821         GL_ScissorTest(false);
7822         CHECKGLERROR
7823 }
7824
7825 void R_RenderWaterPlanes(void)
7826 {
7827         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7828         {
7829                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7830                 if (r_timereport_active)
7831                         R_TimeReport("waterworld");
7832         }
7833
7834         // don't let sound skip if going slow
7835         if (r_refdef.scene.extraupdate)
7836                 S_ExtraUpdate ();
7837
7838         R_DrawModelsAddWaterPlanes();
7839         if (r_timereport_active)
7840                 R_TimeReport("watermodels");
7841
7842         if (r_waterstate.numwaterplanes)
7843         {
7844                 R_Water_ProcessPlanes();
7845                 if (r_timereport_active)
7846                         R_TimeReport("waterscenes");
7847         }
7848 }
7849
7850 extern void R_DrawLightningBeams (void);
7851 extern void VM_CL_AddPolygonsToMeshQueue (void);
7852 extern void R_DrawPortals (void);
7853 extern cvar_t cl_locs_show;
7854 static void R_DrawLocs(void);
7855 static void R_DrawEntityBBoxes(void);
7856 static void R_DrawModelDecals(void);
7857 extern cvar_t cl_decals_newsystem;
7858 extern qboolean r_shadow_usingdeferredprepass;
7859 void R_RenderScene(void)
7860 {
7861         r_refdef.stats.renders++;
7862         r_textureframe++; // used only by R_GetCurrentTexture
7863
7864         R_UpdateFogColor();
7865
7866         // don't let sound skip if going slow
7867         if (r_refdef.scene.extraupdate)
7868                 S_ExtraUpdate ();
7869
7870         R_MeshQueue_BeginScene();
7871
7872         R_SkyStartFrame();
7873
7874         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);
7875
7876         if (cl.csqc_vidvars.drawworld)
7877         {
7878                 // don't let sound skip if going slow
7879                 if (r_refdef.scene.extraupdate)
7880                         S_ExtraUpdate ();
7881
7882                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7883                 {
7884                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7885                         if (r_timereport_active)
7886                                 R_TimeReport("worldsky");
7887                 }
7888
7889                 if (R_DrawBrushModelsSky() && r_timereport_active)
7890                         R_TimeReport("bmodelsky");
7891
7892                 if (skyrendermasked && skyrenderlater)
7893                 {
7894                         // we have to force off the water clipping plane while rendering sky
7895                         R_SetupView(false);
7896                         R_Sky();
7897                         R_SetupView(true);
7898                         if (r_timereport_active)
7899                                 R_TimeReport("sky");
7900                 }
7901         }
7902
7903         R_AnimCache_CacheVisibleEntities();
7904         if (r_timereport_active)
7905                 R_TimeReport("animation");
7906
7907         R_Shadow_PrepareLights();
7908         if (r_timereport_active)
7909                 R_TimeReport("preparelights");
7910
7911         if (r_shadow_usingdeferredprepass)
7912                 R_Shadow_DrawPrepass();
7913
7914         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7915         {
7916                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7917                 if (r_timereport_active)
7918                         R_TimeReport("worlddepth");
7919         }
7920         if (r_depthfirst.integer >= 2)
7921         {
7922                 R_DrawModelsDepth();
7923                 if (r_timereport_active)
7924                         R_TimeReport("modeldepth");
7925         }
7926
7927         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7928         {
7929                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7930                 if (r_timereport_active)
7931                         R_TimeReport("world");
7932         }
7933
7934         // don't let sound skip if going slow
7935         if (r_refdef.scene.extraupdate)
7936                 S_ExtraUpdate ();
7937
7938         R_DrawModels();
7939         if (r_timereport_active)
7940                 R_TimeReport("models");
7941
7942         // don't let sound skip if going slow
7943         if (r_refdef.scene.extraupdate)
7944                 S_ExtraUpdate ();
7945
7946         if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7947         {
7948                 R_DrawModelShadows();
7949                 R_ResetViewRendering3D();
7950                 // don't let sound skip if going slow
7951                 if (r_refdef.scene.extraupdate)
7952                         S_ExtraUpdate ();
7953         }
7954
7955         if (!r_shadow_usingdeferredprepass)
7956         {
7957                 R_Shadow_DrawLights();
7958                 if (r_timereport_active)
7959                         R_TimeReport("rtlights");
7960         }
7961
7962         // don't let sound skip if going slow
7963         if (r_refdef.scene.extraupdate)
7964                 S_ExtraUpdate ();
7965
7966         if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7967         {
7968                 R_DrawModelShadows();
7969                 R_ResetViewRendering3D();
7970                 // don't let sound skip if going slow
7971                 if (r_refdef.scene.extraupdate)
7972                         S_ExtraUpdate ();
7973         }
7974
7975         if (cl.csqc_vidvars.drawworld)
7976         {
7977                 if (cl_decals_newsystem.integer)
7978                 {
7979                         R_DrawModelDecals();
7980                         if (r_timereport_active)
7981                                 R_TimeReport("modeldecals");
7982                 }
7983                 else
7984                 {
7985                         R_DrawDecals();
7986                         if (r_timereport_active)
7987                                 R_TimeReport("decals");
7988                 }
7989
7990                 R_DrawParticles();
7991                 if (r_timereport_active)
7992                         R_TimeReport("particles");
7993
7994                 R_DrawExplosions();
7995                 if (r_timereport_active)
7996                         R_TimeReport("explosions");
7997
7998                 R_DrawLightningBeams();
7999                 if (r_timereport_active)
8000                         R_TimeReport("lightning");
8001         }
8002
8003         VM_CL_AddPolygonsToMeshQueue();
8004
8005         if (r_refdef.view.showdebug)
8006         {
8007                 if (cl_locs_show.integer)
8008                 {
8009                         R_DrawLocs();
8010                         if (r_timereport_active)
8011                                 R_TimeReport("showlocs");
8012                 }
8013
8014                 if (r_drawportals.integer)
8015                 {
8016                         R_DrawPortals();
8017                         if (r_timereport_active)
8018                                 R_TimeReport("portals");
8019                 }
8020
8021                 if (r_showbboxes.value > 0)
8022                 {
8023                         R_DrawEntityBBoxes();
8024                         if (r_timereport_active)
8025                                 R_TimeReport("bboxes");
8026                 }
8027         }
8028
8029         R_MeshQueue_RenderTransparent();
8030         if (r_timereport_active)
8031                 R_TimeReport("drawtrans");
8032
8033         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))
8034         {
8035                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
8036                 if (r_timereport_active)
8037                         R_TimeReport("worlddebug");
8038                 R_DrawModelsDebug();
8039                 if (r_timereport_active)
8040                         R_TimeReport("modeldebug");
8041         }
8042
8043         if (cl.csqc_vidvars.drawworld)
8044         {
8045                 R_Shadow_DrawCoronas();
8046                 if (r_timereport_active)
8047                         R_TimeReport("coronas");
8048         }
8049
8050         // don't let sound skip if going slow
8051         if (r_refdef.scene.extraupdate)
8052                 S_ExtraUpdate ();
8053
8054         R_ResetViewRendering2D();
8055 }
8056
8057 static const unsigned short bboxelements[36] =
8058 {
8059         5, 1, 3, 5, 3, 7,
8060         6, 2, 0, 6, 0, 4,
8061         7, 3, 2, 7, 2, 6,
8062         4, 0, 1, 4, 1, 5,
8063         4, 5, 7, 4, 7, 6,
8064         1, 0, 2, 1, 2, 3,
8065 };
8066
8067 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
8068 {
8069         int i;
8070         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
8071
8072         RSurf_ActiveWorldEntity();
8073
8074         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8075         GL_DepthMask(false);
8076         GL_DepthRange(0, 1);
8077         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8078         R_Mesh_ResetTextureState();
8079
8080         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
8081         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
8082         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
8083         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
8084         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
8085         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
8086         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
8087         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
8088         R_FillColors(color4f, 8, cr, cg, cb, ca);
8089         if (r_refdef.fogenabled)
8090         {
8091                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
8092                 {
8093                         f1 = RSurf_FogVertex(v);
8094                         f2 = 1 - f1;
8095                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
8096                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
8097                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
8098                 }
8099         }
8100         R_Mesh_VertexPointer(vertex3f, 0, 0);
8101         R_Mesh_ColorPointer(color4f, 0, 0);
8102         R_Mesh_ResetTextureState();
8103         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8104         R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
8105 }
8106
8107 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8108 {
8109         int i;
8110         float color[4];
8111         prvm_edict_t *edict;
8112         prvm_prog_t *prog_save = prog;
8113
8114         // this function draws bounding boxes of server entities
8115         if (!sv.active)
8116                 return;
8117
8118         GL_CullFace(GL_NONE);
8119         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8120
8121         prog = 0;
8122         SV_VM_Begin();
8123         for (i = 0;i < numsurfaces;i++)
8124         {
8125                 edict = PRVM_EDICT_NUM(surfacelist[i]);
8126                 switch ((int)edict->fields.server->solid)
8127                 {
8128                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
8129                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
8130                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
8131                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
8132                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
8133                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
8134                 }
8135                 color[3] *= r_showbboxes.value;
8136                 color[3] = bound(0, color[3], 1);
8137                 GL_DepthTest(!r_showdisabledepthtest.integer);
8138                 GL_CullFace(r_refdef.view.cullface_front);
8139                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
8140         }
8141         SV_VM_End();
8142         prog = prog_save;
8143 }
8144
8145 static void R_DrawEntityBBoxes(void)
8146 {
8147         int i;
8148         prvm_edict_t *edict;
8149         vec3_t center;
8150         prvm_prog_t *prog_save = prog;
8151
8152         // this function draws bounding boxes of server entities
8153         if (!sv.active)
8154                 return;
8155
8156         prog = 0;
8157         SV_VM_Begin();
8158         for (i = 0;i < prog->num_edicts;i++)
8159         {
8160                 edict = PRVM_EDICT_NUM(i);
8161                 if (edict->priv.server->free)
8162                         continue;
8163                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
8164                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
8165                         continue;
8166                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
8167                         continue;
8168                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
8169                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
8170         }
8171         SV_VM_End();
8172         prog = prog_save;
8173 }
8174
8175 static const int nomodelelement3i[24] =
8176 {
8177         5, 2, 0,
8178         5, 1, 2,
8179         5, 0, 3,
8180         5, 3, 1,
8181         0, 2, 4,
8182         2, 1, 4,
8183         3, 0, 4,
8184         1, 3, 4
8185 };
8186
8187 static const unsigned short nomodelelement3s[24] =
8188 {
8189         5, 2, 0,
8190         5, 1, 2,
8191         5, 0, 3,
8192         5, 3, 1,
8193         0, 2, 4,
8194         2, 1, 4,
8195         3, 0, 4,
8196         1, 3, 4
8197 };
8198
8199 static const float nomodelvertex3f[6*3] =
8200 {
8201         -16,   0,   0,
8202          16,   0,   0,
8203           0, -16,   0,
8204           0,  16,   0,
8205           0,   0, -16,
8206           0,   0,  16
8207 };
8208
8209 static const float nomodelcolor4f[6*4] =
8210 {
8211         0.0f, 0.0f, 0.5f, 1.0f,
8212         0.0f, 0.0f, 0.5f, 1.0f,
8213         0.0f, 0.5f, 0.0f, 1.0f,
8214         0.0f, 0.5f, 0.0f, 1.0f,
8215         0.5f, 0.0f, 0.0f, 1.0f,
8216         0.5f, 0.0f, 0.0f, 1.0f
8217 };
8218
8219 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8220 {
8221         int i;
8222         float f1, f2, *c;
8223         float color4f[6*4];
8224
8225         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);
8226
8227         // this is only called once per entity so numsurfaces is always 1, and
8228         // surfacelist is always {0}, so this code does not handle batches
8229
8230         if (rsurface.ent_flags & RENDER_ADDITIVE)
8231         {
8232                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
8233                 GL_DepthMask(false);
8234         }
8235         else if (rsurface.colormod[3] < 1)
8236         {
8237                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8238                 GL_DepthMask(false);
8239         }
8240         else
8241         {
8242                 GL_BlendFunc(GL_ONE, GL_ZERO);
8243                 GL_DepthMask(true);
8244         }
8245         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8246         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8247         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8248         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8249         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8250         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
8251         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8252         R_Mesh_ColorPointer(color4f, 0, 0);
8253         for (i = 0, c = color4f;i < 6;i++, c += 4)
8254         {
8255                 c[0] *= rsurface.colormod[0];
8256                 c[1] *= rsurface.colormod[1];
8257                 c[2] *= rsurface.colormod[2];
8258                 c[3] *= rsurface.colormod[3];
8259         }
8260         if (r_refdef.fogenabled)
8261         {
8262                 for (i = 0, c = color4f;i < 6;i++, c += 4)
8263                 {
8264                         f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
8265                         f2 = 1 - f1;
8266                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8267                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8268                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8269                 }
8270         }
8271         R_Mesh_ResetTextureState();
8272         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
8273 }
8274
8275 void R_DrawNoModel(entity_render_t *ent)
8276 {
8277         vec3_t org;
8278         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8279         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8280                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8281         else
8282                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8283 }
8284
8285 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8286 {
8287         vec3_t right1, right2, diff, normal;
8288
8289         VectorSubtract (org2, org1, normal);
8290
8291         // calculate 'right' vector for start
8292         VectorSubtract (r_refdef.view.origin, org1, diff);
8293         CrossProduct (normal, diff, right1);
8294         VectorNormalize (right1);
8295
8296         // calculate 'right' vector for end
8297         VectorSubtract (r_refdef.view.origin, org2, diff);
8298         CrossProduct (normal, diff, right2);
8299         VectorNormalize (right2);
8300
8301         vert[ 0] = org1[0] + width * right1[0];
8302         vert[ 1] = org1[1] + width * right1[1];
8303         vert[ 2] = org1[2] + width * right1[2];
8304         vert[ 3] = org1[0] - width * right1[0];
8305         vert[ 4] = org1[1] - width * right1[1];
8306         vert[ 5] = org1[2] - width * right1[2];
8307         vert[ 6] = org2[0] - width * right2[0];
8308         vert[ 7] = org2[1] - width * right2[1];
8309         vert[ 8] = org2[2] - width * right2[2];
8310         vert[ 9] = org2[0] + width * right2[0];
8311         vert[10] = org2[1] + width * right2[1];
8312         vert[11] = org2[2] + width * right2[2];
8313 }
8314
8315 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)
8316 {
8317         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8318         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8319         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8320         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8321         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8322         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8323         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8324         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8325         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8326         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8327         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8328         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8329 }
8330
8331 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8332 {
8333         int i;
8334         float *vertex3f;
8335         float v[3];
8336         VectorSet(v, x, y, z);
8337         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8338                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8339                         break;
8340         if (i == mesh->numvertices)
8341         {
8342                 if (mesh->numvertices < mesh->maxvertices)
8343                 {
8344                         VectorCopy(v, vertex3f);
8345                         mesh->numvertices++;
8346                 }
8347                 return mesh->numvertices;
8348         }
8349         else
8350                 return i;
8351 }
8352
8353 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8354 {
8355         int i;
8356         int *e, element[3];
8357         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8358         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8359         e = mesh->element3i + mesh->numtriangles * 3;
8360         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8361         {
8362                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8363                 if (mesh->numtriangles < mesh->maxtriangles)
8364                 {
8365                         *e++ = element[0];
8366                         *e++ = element[1];
8367                         *e++ = element[2];
8368                         mesh->numtriangles++;
8369                 }
8370                 element[1] = element[2];
8371         }
8372 }
8373
8374 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8375 {
8376         int i;
8377         int *e, element[3];
8378         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8379         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8380         e = mesh->element3i + mesh->numtriangles * 3;
8381         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8382         {
8383                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8384                 if (mesh->numtriangles < mesh->maxtriangles)
8385                 {
8386                         *e++ = element[0];
8387                         *e++ = element[1];
8388                         *e++ = element[2];
8389                         mesh->numtriangles++;
8390                 }
8391                 element[1] = element[2];
8392         }
8393 }
8394
8395 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8396 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8397 {
8398         int planenum, planenum2;
8399         int w;
8400         int tempnumpoints;
8401         mplane_t *plane, *plane2;
8402         double maxdist;
8403         double temppoints[2][256*3];
8404         // figure out how large a bounding box we need to properly compute this brush
8405         maxdist = 0;
8406         for (w = 0;w < numplanes;w++)
8407                 maxdist = max(maxdist, fabs(planes[w].dist));
8408         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8409         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8410         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8411         {
8412                 w = 0;
8413                 tempnumpoints = 4;
8414                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8415                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8416                 {
8417                         if (planenum2 == planenum)
8418                                 continue;
8419                         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);
8420                         w = !w;
8421                 }
8422                 if (tempnumpoints < 3)
8423                         continue;
8424                 // generate elements forming a triangle fan for this polygon
8425                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8426         }
8427 }
8428
8429 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)
8430 {
8431         texturelayer_t *layer;
8432         layer = t->currentlayers + t->currentnumlayers++;
8433         layer->type = type;
8434         layer->depthmask = depthmask;
8435         layer->blendfunc1 = blendfunc1;
8436         layer->blendfunc2 = blendfunc2;
8437         layer->texture = texture;
8438         layer->texmatrix = *matrix;
8439         layer->color[0] = r;
8440         layer->color[1] = g;
8441         layer->color[2] = b;
8442         layer->color[3] = a;
8443 }
8444
8445 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8446 {
8447         double index, f;
8448         index = parms[2] + r_refdef.scene.time * parms[3];
8449         index -= floor(index);
8450         switch (func)
8451         {
8452         default:
8453         case Q3WAVEFUNC_NONE:
8454         case Q3WAVEFUNC_NOISE:
8455         case Q3WAVEFUNC_COUNT:
8456                 f = 0;
8457                 break;
8458         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8459         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8460         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8461         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8462         case Q3WAVEFUNC_TRIANGLE:
8463                 index *= 4;
8464                 f = index - floor(index);
8465                 if (index < 1)
8466                         f = f;
8467                 else if (index < 2)
8468                         f = 1 - f;
8469                 else if (index < 3)
8470                         f = -f;
8471                 else
8472                         f = -(1 - f);
8473                 break;
8474         }
8475         return (float)(parms[0] + parms[1] * f);
8476 }
8477
8478 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8479 {
8480         int w, h, idx;
8481         float f;
8482         float tcmat[12];
8483         matrix4x4_t matrix, temp;
8484         switch(tcmod->tcmod)
8485         {
8486                 case Q3TCMOD_COUNT:
8487                 case Q3TCMOD_NONE:
8488                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8489                                 matrix = r_waterscrollmatrix;
8490                         else
8491                                 matrix = identitymatrix;
8492                         break;
8493                 case Q3TCMOD_ENTITYTRANSLATE:
8494                         // this is used in Q3 to allow the gamecode to control texcoord
8495                         // scrolling on the entity, which is not supported in darkplaces yet.
8496                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8497                         break;
8498                 case Q3TCMOD_ROTATE:
8499                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8500                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
8501                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8502                         break;
8503                 case Q3TCMOD_SCALE:
8504                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8505                         break;
8506                 case Q3TCMOD_SCROLL:
8507                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
8508                         break;
8509                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8510                         w = (int) tcmod->parms[0];
8511                         h = (int) tcmod->parms[1];
8512                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
8513                         f = f - floor(f);
8514                         idx = (int) floor(f * w * h);
8515                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8516                         break;
8517                 case Q3TCMOD_STRETCH:
8518                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8519                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8520                         break;
8521                 case Q3TCMOD_TRANSFORM:
8522                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8523                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8524                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8525                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8526                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8527                         break;
8528                 case Q3TCMOD_TURBULENT:
8529                         // this is handled in the RSurf_PrepareVertices function
8530                         matrix = identitymatrix;
8531                         break;
8532         }
8533         temp = *texmatrix;
8534         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8535 }
8536
8537 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8538 {
8539         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
8540         char name[MAX_QPATH];
8541         skinframe_t *skinframe;
8542         unsigned char pixels[296*194];
8543         strlcpy(cache->name, skinname, sizeof(cache->name));
8544         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8545         if (developer_loading.integer)
8546                 Con_Printf("loading %s\n", name);
8547         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8548         if (!skinframe || !skinframe->base)
8549         {
8550                 unsigned char *f;
8551                 fs_offset_t filesize;
8552                 skinframe = NULL;
8553                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8554                 if (f)
8555                 {
8556                         if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
8557                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8558                         Mem_Free(f);
8559                 }
8560         }
8561         cache->skinframe = skinframe;
8562 }
8563
8564 texture_t *R_GetCurrentTexture(texture_t *t)
8565 {
8566         int i;
8567         const entity_render_t *ent = rsurface.entity;
8568         dp_model_t *model = ent->model;
8569         q3shaderinfo_layer_tcmod_t *tcmod;
8570
8571         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
8572                 return t->currentframe;
8573         t->update_lastrenderframe = r_textureframe;
8574         t->update_lastrenderentity = (void *)ent;
8575
8576         // switch to an alternate material if this is a q1bsp animated material
8577         {
8578                 texture_t *texture = t;
8579                 int s = rsurface.ent_skinnum;
8580                 if ((unsigned int)s >= (unsigned int)model->numskins)
8581                         s = 0;
8582                 if (model->skinscenes)
8583                 {
8584                         if (model->skinscenes[s].framecount > 1)
8585                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8586                         else
8587                                 s = model->skinscenes[s].firstframe;
8588                 }
8589                 if (s > 0)
8590                         t = t + s * model->num_surfaces;
8591                 if (t->animated)
8592                 {
8593                         // use an alternate animation if the entity's frame is not 0,
8594                         // and only if the texture has an alternate animation
8595                         if (rsurface.ent_alttextures && t->anim_total[1])
8596                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
8597                         else
8598                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
8599                 }
8600                 texture->currentframe = t;
8601         }
8602
8603         // update currentskinframe to be a qw skin or animation frame
8604         if (rsurface.ent_qwskin >= 0)
8605         {
8606                 i = rsurface.ent_qwskin;
8607                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8608                 {
8609                         r_qwskincache_size = cl.maxclients;
8610                         if (r_qwskincache)
8611                                 Mem_Free(r_qwskincache);
8612                         r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8613                 }
8614                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8615                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8616                 t->currentskinframe = r_qwskincache[i].skinframe;
8617                 if (t->currentskinframe == NULL)
8618                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8619         }
8620         else if (t->numskinframes >= 2)
8621                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8622         if (t->backgroundnumskinframes >= 2)
8623                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
8624
8625         t->currentmaterialflags = t->basematerialflags;
8626         t->currentalpha = rsurface.colormod[3];
8627         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
8628                 t->currentalpha *= r_wateralpha.value;
8629         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
8630                 t->currentalpha *= t->r_water_wateralpha;
8631         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
8632                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
8633         if (!(rsurface.ent_flags & RENDER_LIGHT))
8634                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8635         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8636         {
8637                 // pick a model lighting mode
8638                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8639                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8640                 else
8641                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8642         }
8643         if (rsurface.ent_flags & RENDER_ADDITIVE)
8644                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8645         else if (t->currentalpha < 1)
8646                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8647         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8648                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8649         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8650                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8651         if (t->backgroundnumskinframes)
8652                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8653         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8654         {
8655                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
8656                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8657         }
8658         else
8659                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
8660         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8661                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8662
8663         // there is no tcmod
8664         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8665         {
8666                 t->currenttexmatrix = r_waterscrollmatrix;
8667                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8668         }
8669         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8670         {
8671                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8672                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8673         }
8674
8675         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8676                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8677         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8678                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8679
8680         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8681         if (t->currentskinframe->qpixels)
8682                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8683         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8684         if (!t->basetexture)
8685                 t->basetexture = r_texture_notexture;
8686         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8687         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8688         t->nmaptexture = t->currentskinframe->nmap;
8689         if (!t->nmaptexture)
8690                 t->nmaptexture = r_texture_blanknormalmap;
8691         t->glosstexture = r_texture_black;
8692         t->glowtexture = t->currentskinframe->glow;
8693         t->fogtexture = t->currentskinframe->fog;
8694         if (t->backgroundnumskinframes)
8695         {
8696                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8697                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8698                 t->backgroundglosstexture = r_texture_black;
8699                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8700                 if (!t->backgroundnmaptexture)
8701                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8702         }
8703         else
8704         {
8705                 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
8706                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8707                 t->backgroundglosstexture = r_texture_black;
8708                 t->backgroundglowtexture = NULL;
8709         }
8710         t->specularpower = r_shadow_glossexponent.value;
8711         // TODO: store reference values for these in the texture?
8712         t->specularscale = 0;
8713         if (r_shadow_gloss.integer > 0)
8714         {
8715                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8716                 {
8717                         if (r_shadow_glossintensity.value > 0)
8718                         {
8719                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8720                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8721                                 t->specularscale = r_shadow_glossintensity.value;
8722                         }
8723                 }
8724                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8725                 {
8726                         t->glosstexture = r_texture_white;
8727                         t->backgroundglosstexture = r_texture_white;
8728                         t->specularscale = r_shadow_gloss2intensity.value;
8729                         t->specularpower = r_shadow_gloss2exponent.value;
8730                 }
8731         }
8732         t->specularscale *= t->specularscalemod;
8733         t->specularpower *= t->specularpowermod;
8734
8735         // lightmaps mode looks bad with dlights using actual texturing, so turn
8736         // off the colormap and glossmap, but leave the normalmap on as it still
8737         // accurately represents the shading involved
8738         if (gl_lightmaps.integer)
8739         {
8740                 t->basetexture = r_texture_grey128;
8741                 t->pantstexture = r_texture_black;
8742                 t->shirttexture = r_texture_black;
8743                 t->nmaptexture = r_texture_blanknormalmap;
8744                 t->glosstexture = r_texture_black;
8745                 t->glowtexture = NULL;
8746                 t->fogtexture = NULL;
8747                 t->backgroundbasetexture = NULL;
8748                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8749                 t->backgroundglosstexture = r_texture_black;
8750                 t->backgroundglowtexture = NULL;
8751                 t->specularscale = 0;
8752                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8753         }
8754
8755         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8756         VectorClear(t->dlightcolor);
8757         t->currentnumlayers = 0;
8758         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8759         {
8760                 int blendfunc1, blendfunc2;
8761                 qboolean depthmask;
8762                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8763                 {
8764                         blendfunc1 = GL_SRC_ALPHA;
8765                         blendfunc2 = GL_ONE;
8766                 }
8767                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8768                 {
8769                         blendfunc1 = GL_SRC_ALPHA;
8770                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8771                 }
8772                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8773                 {
8774                         blendfunc1 = t->customblendfunc[0];
8775                         blendfunc2 = t->customblendfunc[1];
8776                 }
8777                 else
8778                 {
8779                         blendfunc1 = GL_ONE;
8780                         blendfunc2 = GL_ZERO;
8781                 }
8782                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8783                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8784                 {
8785                         // fullbright is not affected by r_refdef.lightmapintensity
8786                         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]);
8787                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8788                                 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]);
8789                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8790                                 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]);
8791                 }
8792                 else
8793                 {
8794                         vec3_t ambientcolor;
8795                         float colorscale;
8796                         // set the color tint used for lights affecting this surface
8797                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8798                         colorscale = 2;
8799                         // q3bsp has no lightmap updates, so the lightstylevalue that
8800                         // would normally be baked into the lightmap must be
8801                         // applied to the color
8802                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8803                         if (model->type == mod_brushq3)
8804                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8805                         colorscale *= r_refdef.lightmapintensity;
8806                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8807                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8808                         // basic lit geometry
8809                         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]);
8810                         // add pants/shirt if needed
8811                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8812                                 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]);
8813                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8814                                 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]);
8815                         // now add ambient passes if needed
8816                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8817                         {
8818                                 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]);
8819                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8820                                         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]);
8821                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8822                                         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]);
8823                         }
8824                 }
8825                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8826                         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]);
8827                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8828                 {
8829                         // if this is opaque use alpha blend which will darken the earlier
8830                         // passes cheaply.
8831                         //
8832                         // if this is an alpha blended material, all the earlier passes
8833                         // were darkened by fog already, so we only need to add the fog
8834                         // color ontop through the fog mask texture
8835                         //
8836                         // if this is an additive blended material, all the earlier passes
8837                         // were darkened by fog already, and we should not add fog color
8838                         // (because the background was not darkened, there is no fog color
8839                         // that was lost behind it).
8840                         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]);
8841                 }
8842         }
8843
8844         return t->currentframe;
8845 }
8846
8847 rsurfacestate_t rsurface;
8848
8849 void R_Mesh_ResizeArrays(int newvertices)
8850 {
8851         float *base;
8852         if (rsurface.array_size >= newvertices)
8853                 return;
8854         if (rsurface.array_modelvertex3f)
8855                 Mem_Free(rsurface.array_modelvertex3f);
8856         rsurface.array_size = (newvertices + 1023) & ~1023;
8857         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
8858         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
8859         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
8860         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
8861         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
8862         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
8863         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
8864         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
8865         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
8866         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
8867         rsurface.array_color4f           = base + rsurface.array_size * 27;
8868         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
8869 }
8870
8871 void RSurf_ActiveWorldEntity(void)
8872 {
8873         dp_model_t *model = r_refdef.scene.worldmodel;
8874         //if (rsurface.entity == r_refdef.scene.worldentity)
8875         //      return;
8876         rsurface.entity = r_refdef.scene.worldentity;
8877         rsurface.skeleton = NULL;
8878         rsurface.ent_skinnum = 0;
8879         rsurface.ent_qwskin = -1;
8880         rsurface.ent_shadertime = 0;
8881         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8882         if (rsurface.array_size < model->surfmesh.num_vertices)
8883                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
8884         rsurface.matrix = identitymatrix;
8885         rsurface.inversematrix = identitymatrix;
8886         rsurface.matrixscale = 1;
8887         rsurface.inversematrixscale = 1;
8888         R_EntityMatrix(&identitymatrix);
8889         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8890         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8891         rsurface.fograngerecip = r_refdef.fograngerecip;
8892         rsurface.fogheightfade = r_refdef.fogheightfade;
8893         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8894         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8895         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8896         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8897         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8898         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8899         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8900         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8901         rsurface.colormod[3] = 1;
8902         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);
8903         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8904         rsurface.frameblend[0].lerp = 1;
8905         rsurface.ent_alttextures = false;
8906         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8907         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8908         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8909         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
8910         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8911         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8912         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
8913         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8914         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8915         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
8916         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8917         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8918         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
8919         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8920         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8921         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
8922         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8923         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8924         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
8925         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8926         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8927         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
8928         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8929         rsurface.modelelement3i = model->surfmesh.data_element3i;
8930         rsurface.modelelement3s = model->surfmesh.data_element3s;
8931         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
8932         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
8933         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8934         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
8935         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
8936         rsurface.modelsurfaces = model->data_surfaces;
8937         rsurface.generatedvertex = false;
8938         rsurface.vertex3f  = rsurface.modelvertex3f;
8939         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
8940         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8941         rsurface.svector3f = rsurface.modelsvector3f;
8942         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
8943         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8944         rsurface.tvector3f = rsurface.modeltvector3f;
8945         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
8946         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8947         rsurface.normal3f  = rsurface.modelnormal3f;
8948         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
8949         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8950         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
8951 }
8952
8953 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8954 {
8955         dp_model_t *model = ent->model;
8956         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8957         //      return;
8958         rsurface.entity = (entity_render_t *)ent;
8959         rsurface.skeleton = ent->skeleton;
8960         rsurface.ent_skinnum = ent->skinnum;
8961         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;
8962         rsurface.ent_shadertime = ent->shadertime;
8963         rsurface.ent_flags = ent->flags;
8964         if (rsurface.array_size < model->surfmesh.num_vertices)
8965                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
8966         rsurface.matrix = ent->matrix;
8967         rsurface.inversematrix = ent->inversematrix;
8968         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8969         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8970         R_EntityMatrix(&rsurface.matrix);
8971         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8972         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8973         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8974         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8975         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8976         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8977         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8978         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8979         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8980         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8981         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8982         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8983         rsurface.colormod[3] = ent->alpha;
8984         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8985         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8986         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8987         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8988         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8989         if (ent->model->brush.submodel && !prepass)
8990         {
8991                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8992                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8993         }
8994         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
8995         {
8996                 if (ent->animcache_vertex3f && !r_framedata_failed)
8997                 {
8998                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8999                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
9000                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
9001                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
9002                 }
9003                 else if (wanttangents)
9004                 {
9005                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9006                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9007                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9008                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9009                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
9010                 }
9011                 else if (wantnormals)
9012                 {
9013                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9014                         rsurface.modelsvector3f = NULL;
9015                         rsurface.modeltvector3f = NULL;
9016                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9017                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
9018                 }
9019                 else
9020                 {
9021                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9022                         rsurface.modelsvector3f = NULL;
9023                         rsurface.modeltvector3f = NULL;
9024                         rsurface.modelnormal3f = NULL;
9025                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
9026                 }
9027                 rsurface.modelvertex3f_bufferobject = 0;
9028                 rsurface.modelvertex3f_bufferoffset = 0;
9029                 rsurface.modelsvector3f_bufferobject = 0;
9030                 rsurface.modelsvector3f_bufferoffset = 0;
9031                 rsurface.modeltvector3f_bufferobject = 0;
9032                 rsurface.modeltvector3f_bufferoffset = 0;
9033                 rsurface.modelnormal3f_bufferobject = 0;
9034                 rsurface.modelnormal3f_bufferoffset = 0;
9035                 rsurface.generatedvertex = true;
9036         }
9037         else
9038         {
9039                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
9040                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9041                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9042                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9043                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9044                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9045                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9046                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9047                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9048                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
9049                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9050                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9051                 rsurface.generatedvertex = false;
9052         }
9053         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
9054         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9055         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9056         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
9057         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9058         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9059         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
9060         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9061         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9062         rsurface.modelelement3i = model->surfmesh.data_element3i;
9063         rsurface.modelelement3s = model->surfmesh.data_element3s;
9064         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9065         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9066         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9067         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9068         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9069         rsurface.modelsurfaces = model->data_surfaces;
9070         rsurface.vertex3f  = rsurface.modelvertex3f;
9071         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9072         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9073         rsurface.svector3f = rsurface.modelsvector3f;
9074         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9075         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9076         rsurface.tvector3f = rsurface.modeltvector3f;
9077         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9078         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9079         rsurface.normal3f  = rsurface.modelnormal3f;
9080         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9081         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9082         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9083 }
9084
9085 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)
9086 {
9087         rsurface.entity = r_refdef.scene.worldentity;
9088         rsurface.skeleton = NULL;
9089         rsurface.ent_skinnum = 0;
9090         rsurface.ent_qwskin = -1;
9091         rsurface.ent_shadertime = shadertime;
9092         rsurface.ent_flags = entflags;
9093         rsurface.modelnum_vertices = numvertices;
9094         rsurface.modelnum_triangles = numtriangles;
9095         if (rsurface.array_size < rsurface.modelnum_vertices)
9096                 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
9097         rsurface.matrix = *matrix;
9098         rsurface.inversematrix = *inversematrix;
9099         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9100         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9101         R_EntityMatrix(&rsurface.matrix);
9102         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9103         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9104         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9105         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9106         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9107         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9108         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9109         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9110         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9111         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9112         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9113         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
9114         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);
9115         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9116         rsurface.frameblend[0].lerp = 1;
9117         rsurface.ent_alttextures = false;
9118         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9119         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9120         if (wanttangents)
9121         {
9122                 rsurface.modelvertex3f = vertex3f;
9123                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
9124                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
9125                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9126         }
9127         else if (wantnormals)
9128         {
9129                 rsurface.modelvertex3f = vertex3f;
9130                 rsurface.modelsvector3f = NULL;
9131                 rsurface.modeltvector3f = NULL;
9132                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9133         }
9134         else
9135         {
9136                 rsurface.modelvertex3f = vertex3f;
9137                 rsurface.modelsvector3f = NULL;
9138                 rsurface.modeltvector3f = NULL;
9139                 rsurface.modelnormal3f = NULL;
9140         }
9141         rsurface.modelvertex3f_bufferobject = 0;
9142         rsurface.modelvertex3f_bufferoffset = 0;
9143         rsurface.modelsvector3f_bufferobject = 0;
9144         rsurface.modelsvector3f_bufferoffset = 0;
9145         rsurface.modeltvector3f_bufferobject = 0;
9146         rsurface.modeltvector3f_bufferoffset = 0;
9147         rsurface.modelnormal3f_bufferobject = 0;
9148         rsurface.modelnormal3f_bufferoffset = 0;
9149         rsurface.generatedvertex = true;
9150         rsurface.modellightmapcolor4f  = color4f;
9151         rsurface.modellightmapcolor4f_bufferobject = 0;
9152         rsurface.modellightmapcolor4f_bufferoffset = 0;
9153         rsurface.modeltexcoordtexture2f  = texcoord2f;
9154         rsurface.modeltexcoordtexture2f_bufferobject = 0;
9155         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9156         rsurface.modeltexcoordlightmap2f  = NULL;
9157         rsurface.modeltexcoordlightmap2f_bufferobject = 0;
9158         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9159         rsurface.modelelement3i = element3i;
9160         rsurface.modelelement3s = element3s;
9161         rsurface.modelelement3i_bufferobject = 0;
9162         rsurface.modelelement3s_bufferobject = 0;
9163         rsurface.modellightmapoffsets = NULL;
9164         rsurface.modelsurfaces = NULL;
9165         rsurface.vertex3f  = rsurface.modelvertex3f;
9166         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9167         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9168         rsurface.svector3f = rsurface.modelsvector3f;
9169         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9170         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9171         rsurface.tvector3f = rsurface.modeltvector3f;
9172         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9173         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9174         rsurface.normal3f  = rsurface.modelnormal3f;
9175         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9176         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9177         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9178
9179         if (rsurface.modelnum_vertices && rsurface.modelelement3i)
9180         {
9181                 if ((wantnormals || wanttangents) && !normal3f)
9182                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9183                 if (wanttangents && !svector3f)
9184                         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);
9185         }
9186 }
9187
9188 float RSurf_FogPoint(const float *v)
9189 {
9190         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9191         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9192         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9193         float FogHeightFade = r_refdef.fogheightfade;
9194         float fogfrac;
9195         unsigned int fogmasktableindex;
9196         if (r_refdef.fogplaneviewabove)
9197                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9198         else
9199                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9200         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9201         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9202 }
9203
9204 float RSurf_FogVertex(const float *v)
9205 {
9206         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9207         float FogPlaneViewDist = rsurface.fogplaneviewdist;
9208         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9209         float FogHeightFade = rsurface.fogheightfade;
9210         float fogfrac;
9211         unsigned int fogmasktableindex;
9212         if (r_refdef.fogplaneviewabove)
9213                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9214         else
9215                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9216         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9217         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9218 }
9219
9220 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9221 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9222 {
9223         int deformindex;
9224         int texturesurfaceindex;
9225         int i, j;
9226         float amplitude;
9227         float animpos;
9228         float scale;
9229         const float *v1, *in_tc;
9230         float *out_tc;
9231         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9232         float waveparms[4];
9233         q3shaderinfo_deform_t *deform;
9234         // 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
9235         if (rsurface.generatedvertex)
9236         {
9237                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
9238                         generatenormals = true;
9239                 for (i = 0;i < Q3MAXDEFORMS;i++)
9240                 {
9241                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
9242                         {
9243                                 generatetangents = true;
9244                                 generatenormals = true;
9245                         }
9246                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
9247                                 generatenormals = true;
9248                 }
9249                 if (generatenormals && !rsurface.modelnormal3f)
9250                 {
9251                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9252                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
9253                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
9254                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9255                 }
9256                 if (generatetangents && !rsurface.modelsvector3f)
9257                 {
9258                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9259                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
9260                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
9261                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9262                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
9263                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
9264                         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);
9265                 }
9266         }
9267         rsurface.vertex3f  = rsurface.modelvertex3f;
9268         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9269         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9270         rsurface.svector3f = rsurface.modelsvector3f;
9271         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9272         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9273         rsurface.tvector3f = rsurface.modeltvector3f;
9274         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9275         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9276         rsurface.normal3f  = rsurface.modelnormal3f;
9277         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9278         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9279         // if vertices are deformed (sprite flares and things in maps, possibly
9280         // water waves, bulges and other deformations), generate them into
9281         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
9282         // (may be static model data or generated data for an animated model, or
9283         //  the previous deform pass)
9284         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
9285         {
9286                 switch (deform->deform)
9287                 {
9288                 default:
9289                 case Q3DEFORM_PROJECTIONSHADOW:
9290                 case Q3DEFORM_TEXT0:
9291                 case Q3DEFORM_TEXT1:
9292                 case Q3DEFORM_TEXT2:
9293                 case Q3DEFORM_TEXT3:
9294                 case Q3DEFORM_TEXT4:
9295                 case Q3DEFORM_TEXT5:
9296                 case Q3DEFORM_TEXT6:
9297                 case Q3DEFORM_TEXT7:
9298                 case Q3DEFORM_NONE:
9299                         break;
9300                 case Q3DEFORM_AUTOSPRITE:
9301                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9302                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9303                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9304                         VectorNormalize(newforward);
9305                         VectorNormalize(newright);
9306                         VectorNormalize(newup);
9307                         // make deformed versions of only the model vertices used by the specified surfaces
9308                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9309                         {
9310                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9311                                 // a single autosprite surface can contain multiple sprites...
9312                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9313                                 {
9314                                         VectorClear(center);
9315                                         for (i = 0;i < 4;i++)
9316                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9317                                         VectorScale(center, 0.25f, center);
9318                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
9319                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
9320                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
9321                                         for (i = 0;i < 4;i++)
9322                                         {
9323                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
9324                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9325                                         }
9326                                 }
9327                                 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);
9328                                 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);
9329                         }
9330                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9331                         rsurface.vertex3f_bufferobject = 0;
9332                         rsurface.vertex3f_bufferoffset = 0;
9333                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9334                         rsurface.svector3f_bufferobject = 0;
9335                         rsurface.svector3f_bufferoffset = 0;
9336                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9337                         rsurface.tvector3f_bufferobject = 0;
9338                         rsurface.tvector3f_bufferoffset = 0;
9339                         rsurface.normal3f = rsurface.array_deformednormal3f;
9340                         rsurface.normal3f_bufferobject = 0;
9341                         rsurface.normal3f_bufferoffset = 0;
9342                         break;
9343                 case Q3DEFORM_AUTOSPRITE2:
9344                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9345                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9346                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9347                         VectorNormalize(newforward);
9348                         VectorNormalize(newright);
9349                         VectorNormalize(newup);
9350                         // make deformed versions of only the model vertices used by the specified surfaces
9351                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9352                         {
9353                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9354                                 const float *v1, *v2;
9355                                 vec3_t start, end;
9356                                 float f, l;
9357                                 struct
9358                                 {
9359                                         float length2;
9360                                         const float *v1;
9361                                         const float *v2;
9362                                 }
9363                                 shortest[2];
9364                                 memset(shortest, 0, sizeof(shortest));
9365                                 // a single autosprite surface can contain multiple sprites...
9366                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9367                                 {
9368                                         VectorClear(center);
9369                                         for (i = 0;i < 4;i++)
9370                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9371                                         VectorScale(center, 0.25f, center);
9372                                         // find the two shortest edges, then use them to define the
9373                                         // axis vectors for rotating around the central axis
9374                                         for (i = 0;i < 6;i++)
9375                                         {
9376                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
9377                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
9378 #if 0
9379                                                 Debug_PolygonBegin(NULL, 0);
9380                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
9381                                                 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);
9382                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
9383                                                 Debug_PolygonEnd();
9384 #endif
9385                                                 l = VectorDistance2(v1, v2);
9386                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9387                                                 if (v1[2] != v2[2])
9388                                                         l += (1.0f / 1024.0f);
9389                                                 if (shortest[0].length2 > l || i == 0)
9390                                                 {
9391                                                         shortest[1] = shortest[0];
9392                                                         shortest[0].length2 = l;
9393                                                         shortest[0].v1 = v1;
9394                                                         shortest[0].v2 = v2;
9395                                                 }
9396                                                 else if (shortest[1].length2 > l || i == 1)
9397                                                 {
9398                                                         shortest[1].length2 = l;
9399                                                         shortest[1].v1 = v1;
9400                                                         shortest[1].v2 = v2;
9401                                                 }
9402                                         }
9403                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9404                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9405 #if 0
9406                                         Debug_PolygonBegin(NULL, 0);
9407                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
9408                                         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);
9409                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
9410                                         Debug_PolygonEnd();
9411 #endif
9412                                         // this calculates the right vector from the shortest edge
9413                                         // and the up vector from the edge midpoints
9414                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9415                                         VectorNormalize(right);
9416                                         VectorSubtract(end, start, up);
9417                                         VectorNormalize(up);
9418                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9419                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9420                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9421                                         VectorNegate(forward, forward);
9422                                         VectorReflect(forward, 0, up, forward);
9423                                         VectorNormalize(forward);
9424                                         CrossProduct(up, forward, newright);
9425                                         VectorNormalize(newright);
9426 #if 0
9427                                         Debug_PolygonBegin(NULL, 0);
9428                                         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);
9429                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
9430                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
9431                                         Debug_PolygonEnd();
9432 #endif
9433 #if 0
9434                                         Debug_PolygonBegin(NULL, 0);
9435                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
9436                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
9437                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
9438                                         Debug_PolygonEnd();
9439 #endif
9440                                         // rotate the quad around the up axis vector, this is made
9441                                         // especially easy by the fact we know the quad is flat,
9442                                         // so we only have to subtract the center position and
9443                                         // measure distance along the right vector, and then
9444                                         // multiply that by the newright vector and add back the
9445                                         // center position
9446                                         // we also need to subtract the old position to undo the
9447                                         // displacement from the center, which we do with a
9448                                         // DotProduct, the subtraction/addition of center is also
9449                                         // optimized into DotProducts here
9450                                         l = DotProduct(right, center);
9451                                         for (i = 0;i < 4;i++)
9452                                         {
9453                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
9454                                                 f = DotProduct(right, v1) - l;
9455                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9456                                         }
9457                                 }
9458                                 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);
9459                                 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);
9460                         }
9461                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9462                         rsurface.vertex3f_bufferobject = 0;
9463                         rsurface.vertex3f_bufferoffset = 0;
9464                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9465                         rsurface.svector3f_bufferobject = 0;
9466                         rsurface.svector3f_bufferoffset = 0;
9467                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9468                         rsurface.tvector3f_bufferobject = 0;
9469                         rsurface.tvector3f_bufferoffset = 0;
9470                         rsurface.normal3f = rsurface.array_deformednormal3f;
9471                         rsurface.normal3f_bufferobject = 0;
9472                         rsurface.normal3f_bufferoffset = 0;
9473                         break;
9474                 case Q3DEFORM_NORMAL:
9475                         // deform the normals to make reflections wavey
9476                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9477                         {
9478                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9479                                 for (j = 0;j < surface->num_vertices;j++)
9480                                 {
9481                                         float vertex[3];
9482                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
9483                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
9484                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
9485                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9486                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9487                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9488                                         VectorNormalize(normal);
9489                                 }
9490                                 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);
9491                         }
9492                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9493                         rsurface.svector3f_bufferobject = 0;
9494                         rsurface.svector3f_bufferoffset = 0;
9495                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9496                         rsurface.tvector3f_bufferobject = 0;
9497                         rsurface.tvector3f_bufferoffset = 0;
9498                         rsurface.normal3f = rsurface.array_deformednormal3f;
9499                         rsurface.normal3f_bufferobject = 0;
9500                         rsurface.normal3f_bufferoffset = 0;
9501                         break;
9502                 case Q3DEFORM_WAVE:
9503                         // deform vertex array to make wavey water and flags and such
9504                         waveparms[0] = deform->waveparms[0];
9505                         waveparms[1] = deform->waveparms[1];
9506                         waveparms[2] = deform->waveparms[2];
9507                         waveparms[3] = deform->waveparms[3];
9508                         // this is how a divisor of vertex influence on deformation
9509                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9510                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9511                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9512                         {
9513                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9514                                 for (j = 0;j < surface->num_vertices;j++)
9515                                 {
9516                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
9517                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9518                                         // if the wavefunc depends on time, evaluate it per-vertex
9519                                         if (waveparms[3])
9520                                         {
9521                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
9522                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9523                                         }
9524                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9525                                 }
9526                         }
9527                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9528                         rsurface.vertex3f_bufferobject = 0;
9529                         rsurface.vertex3f_bufferoffset = 0;
9530                         break;
9531                 case Q3DEFORM_BULGE:
9532                         // deform vertex array to make the surface have moving bulges
9533                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9534                         {
9535                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9536                                 for (j = 0;j < surface->num_vertices;j++)
9537                                 {
9538                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
9539                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9540                                 }
9541                         }
9542                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9543                         rsurface.vertex3f_bufferobject = 0;
9544                         rsurface.vertex3f_bufferoffset = 0;
9545                         break;
9546                 case Q3DEFORM_MOVE:
9547                         // deform vertex array
9548                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9549                         VectorScale(deform->parms, scale, waveparms);
9550                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9551                         {
9552                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9553                                 for (j = 0;j < surface->num_vertices;j++)
9554                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9555                         }
9556                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9557                         rsurface.vertex3f_bufferobject = 0;
9558                         rsurface.vertex3f_bufferoffset = 0;
9559                         break;
9560                 }
9561         }
9562         // generate texcoords based on the chosen texcoord source
9563         switch(rsurface.texture->tcgen.tcgen)
9564         {
9565         default:
9566         case Q3TCGEN_TEXTURE:
9567                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
9568                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
9569                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9570                 break;
9571         case Q3TCGEN_LIGHTMAP:
9572                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
9573                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
9574                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
9575                 break;
9576         case Q3TCGEN_VECTOR:
9577                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9578                 {
9579                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9580                         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)
9581                         {
9582                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
9583                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
9584                         }
9585                 }
9586                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9587                 rsurface.texcoordtexture2f_bufferobject  = 0;
9588                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9589                 break;
9590         case Q3TCGEN_ENVIRONMENT:
9591                 // make environment reflections using a spheremap
9592                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9593                 {
9594                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9595                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
9596                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
9597                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
9598                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
9599                         {
9600                                 // identical to Q3A's method, but executed in worldspace so
9601                                 // carried models can be shiny too
9602
9603                                 float viewer[3], d, reflected[3], worldreflected[3];
9604
9605                                 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
9606                                 // VectorNormalize(viewer);
9607
9608                                 d = DotProduct(normal, viewer);
9609
9610                                 reflected[0] = normal[0]*2*d - viewer[0];
9611                                 reflected[1] = normal[1]*2*d - viewer[1];
9612                                 reflected[2] = normal[2]*2*d - viewer[2];
9613                                 // note: this is proportinal to viewer, so we can normalize later
9614
9615                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9616                                 VectorNormalize(worldreflected);
9617
9618                                 // note: this sphere map only uses world x and z!
9619                                 // so positive and negative y will LOOK THE SAME.
9620                                 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
9621                                 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
9622                         }
9623                 }
9624                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9625                 rsurface.texcoordtexture2f_bufferobject  = 0;
9626                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9627                 break;
9628         }
9629         // the only tcmod that needs software vertex processing is turbulent, so
9630         // check for it here and apply the changes if needed
9631         // and we only support that as the first one
9632         // (handling a mixture of turbulent and other tcmods would be problematic
9633         //  without punting it entirely to a software path)
9634         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9635         {
9636                 amplitude = rsurface.texture->tcmods[0].parms[1];
9637                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
9638                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9639                 {
9640                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9641                         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)
9642                         {
9643                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9644                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9645                         }
9646                 }
9647                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9648                 rsurface.texcoordtexture2f_bufferobject  = 0;
9649                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9650         }
9651         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
9652         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
9653         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9654         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
9655 }
9656
9657 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9658 {
9659         int i, j;
9660         const msurface_t *surface = texturesurfacelist[0];
9661         const msurface_t *surface2;
9662         int firstvertex;
9663         int endvertex;
9664         int numvertices;
9665         int numtriangles;
9666         // TODO: lock all array ranges before render, rather than on each surface
9667         if (texturenumsurfaces == 1)
9668                 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);
9669         else if (r_batchmode.integer == 2)
9670         {
9671                 #define MAXBATCHTRIANGLES 4096
9672                 int batchtriangles = 0;
9673                 static int batchelements[MAXBATCHTRIANGLES*3];
9674                 for (i = 0;i < texturenumsurfaces;i = j)
9675                 {
9676                         surface = texturesurfacelist[i];
9677                         j = i + 1;
9678                         if (surface->num_triangles > MAXBATCHTRIANGLES)
9679                         {
9680                                 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);
9681                                 continue;
9682                         }
9683                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9684                         batchtriangles = surface->num_triangles;
9685                         firstvertex = surface->num_firstvertex;
9686                         endvertex = surface->num_firstvertex + surface->num_vertices;
9687                         for (;j < texturenumsurfaces;j++)
9688                         {
9689                                 surface2 = texturesurfacelist[j];
9690                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9691                                         break;
9692                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9693                                 batchtriangles += surface2->num_triangles;
9694                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
9695                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9696                         }
9697                         surface2 = texturesurfacelist[j-1];
9698                         numvertices = endvertex - firstvertex;
9699                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9700                 }
9701         }
9702         else if (r_batchmode.integer == 1)
9703         {
9704                 for (i = 0;i < texturenumsurfaces;i = j)
9705                 {
9706                         surface = texturesurfacelist[i];
9707                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9708                                 if (texturesurfacelist[j] != surface2)
9709                                         break;
9710                         surface2 = texturesurfacelist[j-1];
9711                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9712                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9713                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9714                 }
9715         }
9716         else
9717         {
9718                 for (i = 0;i < texturenumsurfaces;i++)
9719                 {
9720                         surface = texturesurfacelist[i];
9721                         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);
9722                 }
9723         }
9724 }
9725
9726 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
9727 {
9728         switch(vid.renderpath)
9729         {
9730         case RENDERPATH_CGGL:
9731 #ifdef SUPPORTCG
9732                 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
9733                 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
9734 #endif
9735                 break;
9736         case RENDERPATH_GL20:
9737                 if (r_glsl_permutation->loc_Texture_Lightmap  >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
9738                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
9739                 break;
9740         case RENDERPATH_GL13:
9741         case RENDERPATH_GL11:
9742                 R_Mesh_TexBind(0, surface->lightmaptexture);
9743                 break;
9744         }
9745 }
9746
9747 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
9748 {
9749         // pick the closest matching water plane and bind textures
9750         int planeindex, vertexindex;
9751         float d, bestd;
9752         vec3_t vert;
9753         const float *v;
9754         r_waterstate_waterplane_t *p, *bestp;
9755         bestd = 0;
9756         bestp = NULL;
9757         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9758         {
9759                 d = 0;
9760                 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
9761                 {
9762                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9763                         d += fabs(PlaneDiff(vert, &p->plane));
9764                 }
9765                 if (bestd > d || !bestp)
9766                 {
9767                         bestd = d;
9768                         bestp = p;
9769                 }
9770         }
9771         switch(vid.renderpath)
9772         {
9773         case RENDERPATH_CGGL:
9774 #ifdef SUPPORTCG
9775                 if (r_cg_permutation->fp_Texture_Refraction) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR
9776                 if (r_cg_permutation->fp_Texture_Reflection) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR
9777 #endif
9778                 break;
9779         case RENDERPATH_GL20:
9780                 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
9781                 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
9782                 break;
9783         case RENDERPATH_GL13:
9784         case RENDERPATH_GL11:
9785                 break;
9786         }
9787 }
9788
9789 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9790 {
9791         int i;
9792         const msurface_t *surface;
9793         if (r_waterstate.renderingscene)
9794                 return;
9795         for (i = 0;i < texturenumsurfaces;i++)
9796         {
9797                 surface = texturesurfacelist[i];
9798                 RSurf_BindLightmapForSurface(surface);
9799                 RSurf_BindReflectionForSurface(surface);
9800                 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);
9801         }
9802 }
9803
9804 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9805 {
9806         int i;
9807         int j;
9808         const msurface_t *surface = texturesurfacelist[0];
9809         const msurface_t *surface2;
9810         int firstvertex;
9811         int endvertex;
9812         int numvertices;
9813         int numtriangles;
9814         if (texturenumsurfaces == 1)
9815         {
9816                 RSurf_BindLightmapForSurface(surface);
9817                 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);
9818         }
9819         else if (r_batchmode.integer == 2)
9820         {
9821 #define MAXBATCHTRIANGLES 4096
9822                 int batchtriangles = 0;
9823                 static int batchelements[MAXBATCHTRIANGLES*3];
9824                 for (i = 0;i < texturenumsurfaces;i = j)
9825                 {
9826                         surface = texturesurfacelist[i];
9827                         RSurf_BindLightmapForSurface(surface);
9828                         j = i + 1;
9829                         if (surface->num_triangles > MAXBATCHTRIANGLES)
9830                         {
9831                                 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);
9832                                 continue;
9833                         }
9834                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9835                         batchtriangles = surface->num_triangles;
9836                         firstvertex = surface->num_firstvertex;
9837                         endvertex = surface->num_firstvertex + surface->num_vertices;
9838                         for (;j < texturenumsurfaces;j++)
9839                         {
9840                                 surface2 = texturesurfacelist[j];
9841                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9842                                         break;
9843                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9844                                 batchtriangles += surface2->num_triangles;
9845                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
9846                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9847                         }
9848                         surface2 = texturesurfacelist[j-1];
9849                         numvertices = endvertex - firstvertex;
9850                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9851                 }
9852         }
9853         else if (r_batchmode.integer == 1)
9854         {
9855 #if 0
9856                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
9857                 for (i = 0;i < texturenumsurfaces;i = j)
9858                 {
9859                         surface = texturesurfacelist[i];
9860                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9861                                 if (texturesurfacelist[j] != surface2)
9862                                         break;
9863                         Con_Printf(" %i", j - i);
9864                 }
9865                 Con_Printf("\n");
9866                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
9867 #endif
9868                 for (i = 0;i < texturenumsurfaces;i = j)
9869                 {
9870                         surface = texturesurfacelist[i];
9871                         RSurf_BindLightmapForSurface(surface);
9872                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9873                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
9874                                         break;
9875 #if 0
9876                         Con_Printf(" %i", j - i);
9877 #endif
9878                         surface2 = texturesurfacelist[j-1];
9879                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9880                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9881                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9882                 }
9883 #if 0
9884                 Con_Printf("\n");
9885 #endif
9886         }
9887         else
9888         {
9889                 for (i = 0;i < texturenumsurfaces;i++)
9890                 {
9891                         surface = texturesurfacelist[i];
9892                         RSurf_BindLightmapForSurface(surface);
9893                         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);
9894                 }
9895         }
9896 }
9897
9898 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9899 {
9900         int j;
9901         int texturesurfaceindex;
9902         if (r_showsurfaces.integer == 2)
9903         {
9904                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9905                 {
9906                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9907                         for (j = 0;j < surface->num_triangles;j++)
9908                         {
9909                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
9910                                 GL_Color(f, f, f, 1);
9911                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9912                         }
9913                 }
9914         }
9915         else
9916         {
9917                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9918                 {
9919                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9920                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
9921                         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);
9922                         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);
9923                 }
9924         }
9925 }
9926
9927 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9928 {
9929         int texturesurfaceindex;
9930         int i;
9931         const float *v;
9932         float *c2;
9933         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9934         {
9935                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9936                 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)
9937                 {
9938                         c2[0] = 0.5;
9939                         c2[1] = 0.5;
9940                         c2[2] = 0.5;
9941                         c2[3] = 1;
9942                 }
9943         }
9944         rsurface.lightmapcolor4f = rsurface.array_color4f;
9945         rsurface.lightmapcolor4f_bufferobject = 0;
9946         rsurface.lightmapcolor4f_bufferoffset = 0;
9947 }
9948
9949 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9950 {
9951         int texturesurfaceindex;
9952         int i;
9953         float f;
9954         const float *v;
9955         const float *c;
9956         float *c2;
9957         if (rsurface.lightmapcolor4f)
9958         {
9959                 // generate color arrays for the surfaces in this list
9960                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9961                 {
9962                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9963                         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)
9964                         {
9965                                 f = RSurf_FogVertex(v);
9966                                 c2[0] = c[0] * f;
9967                                 c2[1] = c[1] * f;
9968                                 c2[2] = c[2] * f;
9969                                 c2[3] = c[3];
9970                         }
9971                 }
9972         }
9973         else
9974         {
9975                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9976                 {
9977                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9978                         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)
9979                         {
9980                                 f = RSurf_FogVertex(v);
9981                                 c2[0] = f;
9982                                 c2[1] = f;
9983                                 c2[2] = f;
9984                                 c2[3] = 1;
9985                         }
9986                 }
9987         }
9988         rsurface.lightmapcolor4f = rsurface.array_color4f;
9989         rsurface.lightmapcolor4f_bufferobject = 0;
9990         rsurface.lightmapcolor4f_bufferoffset = 0;
9991 }
9992
9993 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9994 {
9995         int texturesurfaceindex;
9996         int i;
9997         float f;
9998         const float *v;
9999         const float *c;
10000         float *c2;
10001         if (!rsurface.lightmapcolor4f)
10002                 return;
10003         // generate color arrays for the surfaces in this list
10004         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10005         {
10006                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10007                 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)
10008                 {
10009                         f = RSurf_FogVertex(v);
10010                         c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10011                         c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10012                         c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10013                         c2[3] = c[3];
10014                 }
10015         }
10016         rsurface.lightmapcolor4f = rsurface.array_color4f;
10017         rsurface.lightmapcolor4f_bufferobject = 0;
10018         rsurface.lightmapcolor4f_bufferoffset = 0;
10019 }
10020
10021 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
10022 {
10023         int texturesurfaceindex;
10024         int i;
10025         const float *c;
10026         float *c2;
10027         if (!rsurface.lightmapcolor4f)
10028                 return;
10029         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10030         {
10031                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10032                 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)
10033                 {
10034                         c2[0] = c[0] * r;
10035                         c2[1] = c[1] * g;
10036                         c2[2] = c[2] * b;
10037                         c2[3] = c[3] * a;
10038                 }
10039         }
10040         rsurface.lightmapcolor4f = rsurface.array_color4f;
10041         rsurface.lightmapcolor4f_bufferobject = 0;
10042         rsurface.lightmapcolor4f_bufferoffset = 0;
10043 }
10044
10045 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10046 {
10047         int texturesurfaceindex;
10048         int i;
10049         const float *c;
10050         float *c2;
10051         if (!rsurface.lightmapcolor4f)
10052                 return;
10053         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10054         {
10055                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10056                 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)
10057                 {
10058                         c2[0] = c[0] + r_refdef.scene.ambient;
10059                         c2[1] = c[1] + r_refdef.scene.ambient;
10060                         c2[2] = c[2] + r_refdef.scene.ambient;
10061                         c2[3] = c[3];
10062                 }
10063         }
10064         rsurface.lightmapcolor4f = rsurface.array_color4f;
10065         rsurface.lightmapcolor4f_bufferobject = 0;
10066         rsurface.lightmapcolor4f_bufferoffset = 0;
10067 }
10068
10069 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10070 {
10071         // TODO: optimize
10072         rsurface.lightmapcolor4f = NULL;
10073         rsurface.lightmapcolor4f_bufferobject = 0;
10074         rsurface.lightmapcolor4f_bufferoffset = 0;
10075         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10076         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10077         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10078         GL_Color(r, g, b, a);
10079         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10080 }
10081
10082 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10083 {
10084         // TODO: optimize applyfog && applycolor case
10085         // just apply fog if necessary, and tint the fog color array if necessary
10086         rsurface.lightmapcolor4f = NULL;
10087         rsurface.lightmapcolor4f_bufferobject = 0;
10088         rsurface.lightmapcolor4f_bufferoffset = 0;
10089         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10090         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10091         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10092         GL_Color(r, g, b, a);
10093         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10094 }
10095
10096 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10097 {
10098         int texturesurfaceindex;
10099         int i;
10100         float *c;
10101         // TODO: optimize
10102         if (texturesurfacelist[0]->lightmapinfo)
10103         {
10104                 // generate color arrays for the surfaces in this list
10105                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10106                 {
10107                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10108                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
10109                         {
10110                                 if (surface->lightmapinfo->samples)
10111                                 {
10112                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
10113                                         float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
10114                                         VectorScale(lm, scale, c);
10115                                         if (surface->lightmapinfo->styles[1] != 255)
10116                                         {
10117                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
10118                                                 lm += size3;
10119                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
10120                                                 VectorMA(c, scale, lm, c);
10121                                                 if (surface->lightmapinfo->styles[2] != 255)
10122                                                 {
10123                                                         lm += size3;
10124                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
10125                                                         VectorMA(c, scale, lm, c);
10126                                                         if (surface->lightmapinfo->styles[3] != 255)
10127                                                         {
10128                                                                 lm += size3;
10129                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
10130                                                                 VectorMA(c, scale, lm, c);
10131                                                         }
10132                                                 }
10133                                         }
10134                                 }
10135                                 else
10136                                         VectorClear(c);
10137                                 c[3] = 1;
10138                         }
10139                 }
10140                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10141                 rsurface.lightmapcolor4f_bufferobject = 0;
10142                 rsurface.lightmapcolor4f_bufferoffset = 0;
10143         }
10144         else
10145         {
10146                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10147                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10148                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10149         }
10150         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10151         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10152         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10153         GL_Color(r, g, b, a);
10154         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10155 }
10156
10157 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
10158 {
10159         int texturesurfaceindex;
10160         int i;
10161         float f;
10162         float alpha;
10163         const float *v;
10164         const float *n;
10165         float *c;
10166         vec3_t ambientcolor;
10167         vec3_t diffusecolor;
10168         vec3_t lightdir;
10169         // TODO: optimize
10170         // model lighting
10171         VectorCopy(rsurface.modellight_lightdir, lightdir);
10172         f = 0.5f * r_refdef.lightmapintensity;
10173         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10174         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10175         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10176         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10177         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10178         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10179         alpha = *a;
10180         if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
10181         {
10182                 // generate color arrays for the surfaces in this list
10183                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10184                 {
10185                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10186                         int numverts = surface->num_vertices;
10187                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
10188                         n = rsurface.normal3f + 3 * surface->num_firstvertex;
10189                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
10190                         // q3-style directional shading
10191                         for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
10192                         {
10193                                 if ((f = DotProduct(n, lightdir)) > 0)
10194                                         VectorMA(ambientcolor, f, diffusecolor, c);
10195                                 else
10196                                         VectorCopy(ambientcolor, c);
10197                                 c[3] = alpha;
10198                         }
10199                 }
10200                 *r = 1;
10201                 *g = 1;
10202                 *b = 1;
10203                 *a = 1;
10204                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10205                 rsurface.lightmapcolor4f_bufferobject = 0;
10206                 rsurface.lightmapcolor4f_bufferoffset = 0;
10207                 *applycolor = false;
10208         }
10209         else
10210         {
10211                 *r = ambientcolor[0];
10212                 *g = ambientcolor[1];
10213                 *b = ambientcolor[2];
10214                 rsurface.lightmapcolor4f = NULL;
10215                 rsurface.lightmapcolor4f_bufferobject = 0;
10216                 rsurface.lightmapcolor4f_bufferoffset = 0;
10217         }
10218 }
10219
10220 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10221 {
10222         RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
10223         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10224         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10225         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10226         GL_Color(r, g, b, a);
10227         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10228 }
10229
10230 void RSurf_SetupDepthAndCulling(void)
10231 {
10232         // submodels are biased to avoid z-fighting with world surfaces that they
10233         // may be exactly overlapping (avoids z-fighting artifacts on certain
10234         // doors and things in Quake maps)
10235         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10236         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10237         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10238         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10239 }
10240
10241 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10242 {
10243         // transparent sky would be ridiculous
10244         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10245                 return;
10246         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10247         skyrenderlater = true;
10248         RSurf_SetupDepthAndCulling();
10249         GL_DepthMask(true);
10250         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10251         // skymasking on them, and Quake3 never did sky masking (unlike
10252         // software Quake and software Quake2), so disable the sky masking
10253         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10254         // and skymasking also looks very bad when noclipping outside the
10255         // level, so don't use it then either.
10256         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
10257         {
10258                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10259                 R_Mesh_ColorPointer(NULL, 0, 0);
10260                 R_Mesh_ResetTextureState();
10261                 if (skyrendermasked)
10262                 {
10263                         R_SetupShader_DepthOrShadow();
10264                         // depth-only (masking)
10265                         GL_ColorMask(0,0,0,0);
10266                         // just to make sure that braindead drivers don't draw
10267                         // anything despite that colormask...
10268                         GL_BlendFunc(GL_ZERO, GL_ONE);
10269                 }
10270                 else
10271                 {
10272                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10273                         // fog sky
10274                         GL_BlendFunc(GL_ONE, GL_ZERO);
10275                 }
10276                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10277                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10278                 if (skyrendermasked)
10279                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10280         }
10281         R_Mesh_ResetTextureState();
10282         GL_Color(1, 1, 1, 1);
10283 }
10284
10285 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10286 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10287 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10288 {
10289         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10290         if (prepass)
10291         {
10292                 // render screenspace normalmap to texture
10293                 GL_DepthMask(true);
10294                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
10295                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10296         }
10297         else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !r_waterstate.renderingscene)
10298         {
10299                 // render water or distortion background, then blend surface on top
10300                 GL_DepthMask(true);
10301                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
10302                 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10303                 GL_DepthMask(false);
10304                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
10305                 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10306         }
10307         else
10308         {
10309                 // render surface normally
10310                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10311                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
10312                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
10313                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10314                 else if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10315                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10316                 else
10317                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10318         }
10319 }
10320
10321 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10322 {
10323         // OpenGL 1.3 path - anything not completely ancient
10324         int texturesurfaceindex;
10325         qboolean applycolor;
10326         qboolean applyfog;
10327         int layerindex;
10328         const texturelayer_t *layer;
10329         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10330
10331         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10332         {
10333                 vec4_t layercolor;
10334                 int layertexrgbscale;
10335                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10336                 {
10337                         if (layerindex == 0)
10338                                 GL_AlphaTest(true);
10339                         else
10340                         {
10341                                 GL_AlphaTest(false);
10342                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10343                         }
10344                 }
10345                 GL_DepthMask(layer->depthmask && writedepth);
10346                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10347                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10348                 {
10349                         layertexrgbscale = 4;
10350                         VectorScale(layer->color, 0.25f, layercolor);
10351                 }
10352                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10353                 {
10354                         layertexrgbscale = 2;
10355                         VectorScale(layer->color, 0.5f, layercolor);
10356                 }
10357                 else
10358                 {
10359                         layertexrgbscale = 1;
10360                         VectorScale(layer->color, 1.0f, layercolor);
10361                 }
10362                 layercolor[3] = layer->color[3];
10363                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10364                 R_Mesh_ColorPointer(NULL, 0, 0);
10365                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10366                 switch (layer->type)
10367                 {
10368                 case TEXTURELAYERTYPE_LITTEXTURE:
10369                         // single-pass lightmapped texture with 2x rgbscale
10370                         //R_Mesh_TexBind(0, r_texture_white);
10371                         R_Mesh_TexMatrix(0, NULL);
10372                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10373                         R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10374                         R_Mesh_TexBind(1, layer->texture);
10375                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10376                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10377                         R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10378                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10379                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10380                         else if (rsurface.uselightmaptexture)
10381                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10382                         else
10383                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10384                         break;
10385                 case TEXTURELAYERTYPE_TEXTURE:
10386                         // singletexture unlit texture with transparency support
10387                         R_Mesh_TexBind(0, layer->texture);
10388                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10389                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10390                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10391                         R_Mesh_TexBind(1, 0);
10392                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10393                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10394                         break;
10395                 case TEXTURELAYERTYPE_FOG:
10396                         // singletexture fogging
10397                         if (layer->texture)
10398                         {
10399                                 R_Mesh_TexBind(0, layer->texture);
10400                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10401                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10402                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10403                         }
10404                         else
10405                         {
10406                                 R_Mesh_TexBind(0, 0);
10407                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10408                         }
10409                         R_Mesh_TexBind(1, 0);
10410                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10411                         // generate a color array for the fog pass
10412                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10413                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10414                         {
10415                                 int i;
10416                                 float f;
10417                                 const float *v;
10418                                 float *c;
10419                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10420                                 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)
10421                                 {
10422                                         f = 1 - RSurf_FogVertex(v);
10423                                         c[0] = layercolor[0];
10424                                         c[1] = layercolor[1];
10425                                         c[2] = layercolor[2];
10426                                         c[3] = f * layercolor[3];
10427                                 }
10428                         }
10429                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10430                         break;
10431                 default:
10432                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10433                 }
10434         }
10435         CHECKGLERROR
10436         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10437         {
10438                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10439                 GL_AlphaTest(false);
10440         }
10441 }
10442
10443 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10444 {
10445         // OpenGL 1.1 - crusty old voodoo path
10446         int texturesurfaceindex;
10447         qboolean applyfog;
10448         int layerindex;
10449         const texturelayer_t *layer;
10450         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10451
10452         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10453         {
10454                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10455                 {
10456                         if (layerindex == 0)
10457                                 GL_AlphaTest(true);
10458                         else
10459                         {
10460                                 GL_AlphaTest(false);
10461                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10462                         }
10463                 }
10464                 GL_DepthMask(layer->depthmask && writedepth);
10465                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10466                 R_Mesh_ColorPointer(NULL, 0, 0);
10467                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10468                 switch (layer->type)
10469                 {
10470                 case TEXTURELAYERTYPE_LITTEXTURE:
10471                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10472                         {
10473                                 // two-pass lit texture with 2x rgbscale
10474                                 // first the lightmap pass
10475                                 //R_Mesh_TexBind(0, r_texture_white);
10476                                 R_Mesh_TexMatrix(0, NULL);
10477                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10478                                 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10479                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10480                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10481                                 else if (rsurface.uselightmaptexture)
10482                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10483                                 else
10484                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10485                                 // then apply the texture to it
10486                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10487                                 R_Mesh_TexBind(0, layer->texture);
10488                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10489                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10490                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10491                                 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);
10492                         }
10493                         else
10494                         {
10495                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10496                                 R_Mesh_TexBind(0, layer->texture);
10497                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10498                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10499                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10500                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10501                                         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);
10502                                 else
10503                                         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);
10504                         }
10505                         break;
10506                 case TEXTURELAYERTYPE_TEXTURE:
10507                         // singletexture unlit texture with transparency support
10508                         R_Mesh_TexBind(0, layer->texture);
10509                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10510                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10511                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10512                         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);
10513                         break;
10514                 case TEXTURELAYERTYPE_FOG:
10515                         // singletexture fogging
10516                         if (layer->texture)
10517                         {
10518                                 R_Mesh_TexBind(0, layer->texture);
10519                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10520                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10521                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10522                         }
10523                         else
10524                         {
10525                                 R_Mesh_TexBind(0, 0);
10526                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10527                         }
10528                         // generate a color array for the fog pass
10529                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10530                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10531                         {
10532                                 int i;
10533                                 float f;
10534                                 const float *v;
10535                                 float *c;
10536                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10537                                 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)
10538                                 {
10539                                         f = 1 - RSurf_FogVertex(v);
10540                                         c[0] = layer->color[0];
10541                                         c[1] = layer->color[1];
10542                                         c[2] = layer->color[2];
10543                                         c[3] = f * layer->color[3];
10544                                 }
10545                         }
10546                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10547                         break;
10548                 default:
10549                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10550                 }
10551         }
10552         CHECKGLERROR
10553         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10554         {
10555                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10556                 GL_AlphaTest(false);
10557         }
10558 }
10559
10560 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10561 {
10562         float c[4];
10563
10564         GL_AlphaTest(false);
10565         R_Mesh_ColorPointer(NULL, 0, 0);
10566         R_Mesh_ResetTextureState();
10567         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10568
10569         if(rsurface.texture && rsurface.texture->currentskinframe)
10570         {
10571                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10572                 c[3] *= rsurface.texture->currentalpha;
10573         }
10574         else
10575         {
10576                 c[0] = 1;
10577                 c[1] = 0;
10578                 c[2] = 1;
10579                 c[3] = 1;
10580         }
10581
10582         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10583         {
10584                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10585                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10586                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10587         }
10588
10589         // brighten it up (as texture value 127 means "unlit")
10590         c[0] *= 2 * r_refdef.view.colorscale;
10591         c[1] *= 2 * r_refdef.view.colorscale;
10592         c[2] *= 2 * r_refdef.view.colorscale;
10593
10594         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10595                 c[3] *= r_wateralpha.value;
10596
10597         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10598         {
10599                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10600                 GL_DepthMask(false);
10601         }
10602         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10603         {
10604                 GL_BlendFunc(GL_ONE, GL_ONE);
10605                 GL_DepthMask(false);
10606         }
10607         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10608         {
10609                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10610                 GL_DepthMask(false);
10611         }
10612         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10613         {
10614                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10615                 GL_DepthMask(false);
10616         }
10617         else
10618         {
10619                 GL_BlendFunc(GL_ONE, GL_ZERO);
10620                 GL_DepthMask(writedepth);
10621         }
10622
10623         rsurface.lightmapcolor4f = NULL;
10624
10625         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10626         {
10627                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10628
10629                 rsurface.lightmapcolor4f = NULL;
10630                 rsurface.lightmapcolor4f_bufferobject = 0;
10631                 rsurface.lightmapcolor4f_bufferoffset = 0;
10632         }
10633         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10634         {
10635                 qboolean applycolor = true;
10636                 float one = 1.0;
10637
10638                 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10639
10640                 r_refdef.lightmapintensity = 1;
10641                 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
10642                 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10643         }
10644         else
10645         {
10646                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10647
10648                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10649                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10650                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10651         }
10652
10653         if(!rsurface.lightmapcolor4f)
10654                 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
10655
10656         RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
10657         RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
10658         if(r_refdef.fogenabled)
10659                 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
10660
10661         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10662         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10663 }
10664
10665 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10666 {
10667         CHECKGLERROR
10668         RSurf_SetupDepthAndCulling();
10669         if (r_showsurfaces.integer == 3 && !prepass)
10670         {
10671                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10672                 return;
10673         }
10674         switch (vid.renderpath)
10675         {
10676         case RENDERPATH_GL20:
10677         case RENDERPATH_CGGL:
10678                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10679                 break;
10680         case RENDERPATH_GL13:
10681                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10682                 break;
10683         case RENDERPATH_GL11:
10684                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10685                 break;
10686         }
10687         CHECKGLERROR
10688 }
10689
10690 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10691 {
10692         CHECKGLERROR
10693         RSurf_SetupDepthAndCulling();
10694         if (r_showsurfaces.integer == 3 && !prepass)
10695         {
10696                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10697                 return;
10698         }
10699         switch (vid.renderpath)
10700         {
10701         case RENDERPATH_GL20:
10702         case RENDERPATH_CGGL:
10703                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10704                 break;
10705         case RENDERPATH_GL13:
10706                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10707                 break;
10708         case RENDERPATH_GL11:
10709                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10710                 break;
10711         }
10712         CHECKGLERROR
10713 }
10714
10715 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10716 {
10717         int i, j;
10718         int texturenumsurfaces, endsurface;
10719         texture_t *texture;
10720         const msurface_t *surface;
10721         const msurface_t *texturesurfacelist[256];
10722
10723         // if the model is static it doesn't matter what value we give for
10724         // wantnormals and wanttangents, so this logic uses only rules applicable
10725         // to a model, knowing that they are meaningless otherwise
10726         if (ent == r_refdef.scene.worldentity)
10727                 RSurf_ActiveWorldEntity();
10728         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10729                 RSurf_ActiveModelEntity(ent, false, false, false);
10730         else
10731         {
10732                 switch (vid.renderpath)
10733                 {
10734                 case RENDERPATH_GL20:
10735                 case RENDERPATH_CGGL:
10736                         RSurf_ActiveModelEntity(ent, true, true, false);
10737                         break;
10738                 case RENDERPATH_GL13:
10739                 case RENDERPATH_GL11:
10740                         RSurf_ActiveModelEntity(ent, true, false, false);
10741                         break;
10742                 }
10743         }
10744
10745         if (r_transparentdepthmasking.integer)
10746         {
10747                 qboolean setup = false;
10748                 for (i = 0;i < numsurfaces;i = j)
10749                 {
10750                         j = i + 1;
10751                         surface = rsurface.modelsurfaces + surfacelist[i];
10752                         texture = surface->texture;
10753                         rsurface.texture = R_GetCurrentTexture(texture);
10754                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10755                         // scan ahead until we find a different texture
10756                         endsurface = min(i + 1024, numsurfaces);
10757                         texturenumsurfaces = 0;
10758                         texturesurfacelist[texturenumsurfaces++] = surface;
10759                         for (;j < endsurface;j++)
10760                         {
10761                                 surface = rsurface.modelsurfaces + surfacelist[j];
10762                                 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10763                                         break;
10764                                 texturesurfacelist[texturenumsurfaces++] = surface;
10765                         }
10766                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10767                                 continue;
10768                         // render the range of surfaces as depth
10769                         if (!setup)
10770                         {
10771                                 setup = true;
10772                                 GL_ColorMask(0,0,0,0);
10773                                 GL_Color(1,1,1,1);
10774                                 GL_DepthTest(true);
10775                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10776                                 GL_DepthMask(true);
10777                                 GL_AlphaTest(false);
10778                                 R_Mesh_ColorPointer(NULL, 0, 0);
10779                                 R_Mesh_ResetTextureState();
10780                                 R_SetupShader_DepthOrShadow();
10781                         }
10782                         RSurf_SetupDepthAndCulling();
10783                         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10784                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10785                 }
10786                 if (setup)
10787                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10788         }
10789
10790         for (i = 0;i < numsurfaces;i = j)
10791         {
10792                 j = i + 1;
10793                 surface = rsurface.modelsurfaces + surfacelist[i];
10794                 texture = surface->texture;
10795                 rsurface.texture = R_GetCurrentTexture(texture);
10796                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10797                 // scan ahead until we find a different texture
10798                 endsurface = min(i + 1024, numsurfaces);
10799                 texturenumsurfaces = 0;
10800                 texturesurfacelist[texturenumsurfaces++] = surface;
10801                 for (;j < endsurface;j++)
10802                 {
10803                         surface = rsurface.modelsurfaces + surfacelist[j];
10804                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10805                                 break;
10806                         texturesurfacelist[texturenumsurfaces++] = surface;
10807                 }
10808                 // render the range of surfaces
10809                 if (ent == r_refdef.scene.worldentity)
10810                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10811                 else
10812                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10813         }
10814         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10815         GL_AlphaTest(false);
10816 }
10817
10818 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10819 {
10820         // transparent surfaces get pushed off into the transparent queue
10821         int surfacelistindex;
10822         const msurface_t *surface;
10823         vec3_t tempcenter, center;
10824         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10825         {
10826                 surface = texturesurfacelist[surfacelistindex];
10827                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10828                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10829                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10830                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10831                 if (queueentity->transparent_offset) // transparent offset
10832                 {
10833                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10834                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10835                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10836                 }
10837                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10838         }
10839 }
10840
10841 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10842 {
10843         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10844         CHECKGLERROR
10845         if (depthonly)
10846         {
10847                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10848                         return;
10849                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10850                         return;
10851                 RSurf_SetupDepthAndCulling();
10852                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10853                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10854         }
10855         else if (prepass)
10856         {
10857                 if (!rsurface.texture->currentnumlayers)
10858                         return;
10859                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10860                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10861                 else
10862                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10863         }
10864         else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
10865         {
10866                 RSurf_SetupDepthAndCulling();
10867                 GL_AlphaTest(false);
10868                 R_Mesh_ColorPointer(NULL, 0, 0);
10869                 R_Mesh_ResetTextureState();
10870                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10871                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10872                 GL_DepthMask(true);
10873                 GL_BlendFunc(GL_ONE, GL_ZERO);
10874                 GL_Color(0, 0, 0, 1);
10875                 GL_DepthTest(writedepth);
10876                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10877         }
10878         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
10879         {
10880                 RSurf_SetupDepthAndCulling();
10881                 GL_AlphaTest(false);
10882                 R_Mesh_ColorPointer(NULL, 0, 0);
10883                 R_Mesh_ResetTextureState();
10884                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10885                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10886                 GL_DepthMask(true);
10887                 GL_BlendFunc(GL_ONE, GL_ZERO);
10888                 GL_DepthTest(true);
10889                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
10890         }
10891         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
10892                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10893         else if (!rsurface.texture->currentnumlayers)
10894                 return;
10895         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10896         {
10897                 // in the deferred case, transparent surfaces were queued during prepass
10898                 if (!r_shadow_usingdeferredprepass)
10899                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10900         }
10901         else
10902         {
10903                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10904                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10905         }
10906         CHECKGLERROR
10907 }
10908
10909 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10910 {
10911         int i, j;
10912         texture_t *texture;
10913         // break the surface list down into batches by texture and use of lightmapping
10914         for (i = 0;i < numsurfaces;i = j)
10915         {
10916                 j = i + 1;
10917                 // texture is the base texture pointer, rsurface.texture is the
10918                 // current frame/skin the texture is directing us to use (for example
10919                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10920                 // use skin 1 instead)
10921                 texture = surfacelist[i]->texture;
10922                 rsurface.texture = R_GetCurrentTexture(texture);
10923                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
10924                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10925                 {
10926                         // if this texture is not the kind we want, skip ahead to the next one
10927                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10928                                 ;
10929                         continue;
10930                 }
10931                 // simply scan ahead until we find a different texture or lightmap state
10932                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
10933                         ;
10934                 // render the range of surfaces
10935                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10936         }
10937 }
10938
10939 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10940 {
10941         CHECKGLERROR
10942         if (depthonly)
10943         {
10944                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10945                         return;
10946                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10947                         return;
10948                 RSurf_SetupDepthAndCulling();
10949                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10950                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10951         }
10952         else if (prepass)
10953         {
10954                 if (!rsurface.texture->currentnumlayers)
10955                         return;
10956                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10957                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10958                 else
10959                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10960         }
10961         else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
10962         {
10963                 RSurf_SetupDepthAndCulling();
10964                 GL_AlphaTest(false);
10965                 R_Mesh_ColorPointer(NULL, 0, 0);
10966                 R_Mesh_ResetTextureState();
10967                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10968                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10969                 GL_DepthMask(true);
10970                 GL_BlendFunc(GL_ONE, GL_ZERO);
10971                 GL_Color(0, 0, 0, 1);
10972                 GL_DepthTest(writedepth);
10973                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10974         }
10975         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10976         {
10977                 RSurf_SetupDepthAndCulling();
10978                 GL_AlphaTest(false);
10979                 R_Mesh_ColorPointer(NULL, 0, 0);
10980                 R_Mesh_ResetTextureState();
10981                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10982                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10983                 GL_DepthMask(true);
10984                 GL_BlendFunc(GL_ONE, GL_ZERO);
10985                 GL_DepthTest(true);
10986                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
10987         }
10988         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
10989                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10990         else if (!rsurface.texture->currentnumlayers)
10991                 return;
10992         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10993         {
10994                 // in the deferred case, transparent surfaces were queued during prepass
10995                 if (!r_shadow_usingdeferredprepass)
10996                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10997         }
10998         else
10999         {
11000                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11001                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11002         }
11003         CHECKGLERROR
11004 }
11005
11006 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11007 {
11008         int i, j;
11009         texture_t *texture;
11010         // break the surface list down into batches by texture and use of lightmapping
11011         for (i = 0;i < numsurfaces;i = j)
11012         {
11013                 j = i + 1;
11014                 // texture is the base texture pointer, rsurface.texture is the
11015                 // current frame/skin the texture is directing us to use (for example
11016                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11017                 // use skin 1 instead)
11018                 texture = surfacelist[i]->texture;
11019                 rsurface.texture = R_GetCurrentTexture(texture);
11020                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11021                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11022                 {
11023                         // if this texture is not the kind we want, skip ahead to the next one
11024                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11025                                 ;
11026                         continue;
11027                 }
11028                 // simply scan ahead until we find a different texture or lightmap state
11029                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11030                         ;
11031                 // render the range of surfaces
11032                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
11033         }
11034 }
11035
11036 float locboxvertex3f[6*4*3] =
11037 {
11038         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11039         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11040         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11041         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11042         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11043         1,0,0, 0,0,0, 0,1,0, 1,1,0
11044 };
11045
11046 unsigned short locboxelements[6*2*3] =
11047 {
11048          0, 1, 2, 0, 2, 3,
11049          4, 5, 6, 4, 6, 7,
11050          8, 9,10, 8,10,11,
11051         12,13,14, 12,14,15,
11052         16,17,18, 16,18,19,
11053         20,21,22, 20,22,23
11054 };
11055
11056 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11057 {
11058         int i, j;
11059         cl_locnode_t *loc = (cl_locnode_t *)ent;
11060         vec3_t mins, size;
11061         float vertex3f[6*4*3];
11062         CHECKGLERROR
11063         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11064         GL_DepthMask(false);
11065         GL_DepthRange(0, 1);
11066         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11067         GL_DepthTest(true);
11068         GL_CullFace(GL_NONE);
11069         R_EntityMatrix(&identitymatrix);
11070
11071         R_Mesh_VertexPointer(vertex3f, 0, 0);
11072         R_Mesh_ColorPointer(NULL, 0, 0);
11073         R_Mesh_ResetTextureState();
11074         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11075
11076         i = surfacelist[0];
11077         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11078                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11079                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11080                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11081
11082         if (VectorCompare(loc->mins, loc->maxs))
11083         {
11084                 VectorSet(size, 2, 2, 2);
11085                 VectorMA(loc->mins, -0.5f, size, mins);
11086         }
11087         else
11088         {
11089                 VectorCopy(loc->mins, mins);
11090                 VectorSubtract(loc->maxs, loc->mins, size);
11091         }
11092
11093         for (i = 0;i < 6*4*3;)
11094                 for (j = 0;j < 3;j++, i++)
11095                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11096
11097         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
11098 }
11099
11100 void R_DrawLocs(void)
11101 {
11102         int index;
11103         cl_locnode_t *loc, *nearestloc;
11104         vec3_t center;
11105         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11106         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11107         {
11108                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11109                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11110         }
11111 }
11112
11113 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11114 {
11115         if (decalsystem->decals)
11116                 Mem_Free(decalsystem->decals);
11117         memset(decalsystem, 0, sizeof(*decalsystem));
11118 }
11119
11120 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)
11121 {
11122         tridecal_t *decal;
11123         tridecal_t *decals;
11124         int i;
11125         int maxdecals;
11126
11127         // expand or initialize the system
11128         if (decalsystem->maxdecals <= decalsystem->numdecals)
11129         {
11130                 decalsystem_t old = *decalsystem;
11131                 qboolean useshortelements;
11132                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11133                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11134                 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)));
11135                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11136                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11137                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11138                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11139                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11140                 if (decalsystem->numdecals)
11141                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11142                 if (old.decals)
11143                         Mem_Free(old.decals);
11144                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11145                         decalsystem->element3i[i] = i;
11146                 if (useshortelements)
11147                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11148                                 decalsystem->element3s[i] = i;
11149         }
11150
11151         // grab a decal and search for another free slot for the next one
11152         maxdecals = decalsystem->maxdecals;
11153         decals = decalsystem->decals;
11154         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11155         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
11156                 ;
11157         decalsystem->freedecal = i;
11158         if (decalsystem->numdecals <= i)
11159                 decalsystem->numdecals = i + 1;
11160
11161         // initialize the decal
11162         decal->lived = 0;
11163         decal->triangleindex = triangleindex;
11164         decal->surfaceindex = surfaceindex;
11165         decal->decalsequence = decalsequence;
11166         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
11167         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
11168         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
11169         decal->color4ub[0][3] = 255;
11170         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
11171         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
11172         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
11173         decal->color4ub[1][3] = 255;
11174         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
11175         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
11176         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
11177         decal->color4ub[2][3] = 255;
11178         decal->vertex3f[0][0] = v0[0];
11179         decal->vertex3f[0][1] = v0[1];
11180         decal->vertex3f[0][2] = v0[2];
11181         decal->vertex3f[1][0] = v1[0];
11182         decal->vertex3f[1][1] = v1[1];
11183         decal->vertex3f[1][2] = v1[2];
11184         decal->vertex3f[2][0] = v2[0];
11185         decal->vertex3f[2][1] = v2[1];
11186         decal->vertex3f[2][2] = v2[2];
11187         decal->texcoord2f[0][0] = t0[0];
11188         decal->texcoord2f[0][1] = t0[1];
11189         decal->texcoord2f[1][0] = t1[0];
11190         decal->texcoord2f[1][1] = t1[1];
11191         decal->texcoord2f[2][0] = t2[0];
11192         decal->texcoord2f[2][1] = t2[1];
11193 }
11194
11195 extern cvar_t cl_decals_bias;
11196 extern cvar_t cl_decals_models;
11197 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11198 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)
11199 {
11200         matrix4x4_t projection;
11201         decalsystem_t *decalsystem;
11202         qboolean dynamic;
11203         dp_model_t *model;
11204         const float *vertex3f;
11205         const msurface_t *surface;
11206         const msurface_t *surfaces;
11207         const int *surfacelist;
11208         const texture_t *texture;
11209         int numvertices;
11210         int numtriangles;
11211         int numsurfacelist;
11212         int surfacelistindex;
11213         int surfaceindex;
11214         int triangleindex;
11215         int decalsurfaceindex;
11216         int cornerindex;
11217         int index;
11218         int numpoints;
11219         const int *e;
11220         float localorigin[3];
11221         float localnormal[3];
11222         float localmins[3];
11223         float localmaxs[3];
11224         float localsize;
11225         float ilocalsize;
11226         float v[9][3];
11227         float tc[9][2];
11228         float c[9][4];
11229         //float normal[3];
11230         float planes[6][4];
11231         float f;
11232         float points[2][9][3];
11233         float angles[3];
11234         float temp[3];
11235
11236         decalsystem = &ent->decalsystem;
11237         model = ent->model;
11238         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11239         {
11240                 R_DecalSystem_Reset(&ent->decalsystem);
11241                 return;
11242         }
11243
11244         if (!model->brush.data_nodes && !cl_decals_models.integer)
11245         {
11246                 if (decalsystem->model)
11247                         R_DecalSystem_Reset(decalsystem);
11248                 return;
11249         }
11250
11251         if (decalsystem->model != model)
11252                 R_DecalSystem_Reset(decalsystem);
11253         decalsystem->model = model;
11254
11255         RSurf_ActiveModelEntity(ent, false, false, false);
11256
11257         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11258         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11259         VectorNormalize(localnormal);
11260         localsize = worldsize*rsurface.inversematrixscale;
11261         ilocalsize = 1.0f / localsize;
11262         localmins[0] = localorigin[0] - localsize;
11263         localmins[1] = localorigin[1] - localsize;
11264         localmins[2] = localorigin[2] - localsize;
11265         localmaxs[0] = localorigin[0] + localsize;
11266         localmaxs[1] = localorigin[1] + localsize;
11267         localmaxs[2] = localorigin[2] + localsize;
11268
11269         //VectorCopy(localnormal, planes[4]);
11270         //VectorVectors(planes[4], planes[2], planes[0]);
11271         AnglesFromVectors(angles, localnormal, NULL, false);
11272         AngleVectors(angles, planes[0], planes[2], planes[4]);
11273         VectorNegate(planes[0], planes[1]);
11274         VectorNegate(planes[2], planes[3]);
11275         VectorNegate(planes[4], planes[5]);
11276         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11277         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11278         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11279         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11280         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11281         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11282
11283 #if 1
11284 // works
11285 {
11286         matrix4x4_t forwardprojection;
11287         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11288         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11289 }
11290 #else
11291 // broken
11292 {
11293         float projectionvector[4][3];
11294         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11295         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11296         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11297         projectionvector[0][0] = planes[0][0] * ilocalsize;
11298         projectionvector[0][1] = planes[1][0] * ilocalsize;
11299         projectionvector[0][2] = planes[2][0] * ilocalsize;
11300         projectionvector[1][0] = planes[0][1] * ilocalsize;
11301         projectionvector[1][1] = planes[1][1] * ilocalsize;
11302         projectionvector[1][2] = planes[2][1] * ilocalsize;
11303         projectionvector[2][0] = planes[0][2] * ilocalsize;
11304         projectionvector[2][1] = planes[1][2] * ilocalsize;
11305         projectionvector[2][2] = planes[2][2] * ilocalsize;
11306         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11307         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11308         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11309         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11310 }
11311 #endif
11312
11313         dynamic = model->surfmesh.isanimated;
11314         vertex3f = rsurface.modelvertex3f;
11315         numsurfacelist = model->nummodelsurfaces;
11316         surfacelist = model->sortedmodelsurfaces;
11317         surfaces = model->data_surfaces;
11318         for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11319         {
11320                 surfaceindex = surfacelist[surfacelistindex];
11321                 surface = surfaces + surfaceindex;
11322                 // skip transparent surfaces
11323                 texture = surface->texture;
11324                 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11325                         continue;
11326                 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11327                         continue;
11328                 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11329                         continue;
11330                 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
11331                 numvertices = surface->num_vertices;
11332                 numtriangles = surface->num_triangles;
11333                 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
11334                 {
11335                         for (cornerindex = 0;cornerindex < 3;cornerindex++)
11336                         {
11337                                 index = 3*e[cornerindex];
11338                                 VectorCopy(vertex3f + index, v[cornerindex]);
11339                         }
11340                         // cull backfaces
11341                         //TriangleNormal(v[0], v[1], v[2], normal);
11342                         //if (DotProduct(normal, localnormal) < 0.0f)
11343                         //      continue;
11344                         // clip by each of the box planes formed from the projection matrix
11345                         // if anything survives, we emit the decal
11346                         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]);
11347                         if (numpoints < 3)
11348                                 continue;
11349                         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]);
11350                         if (numpoints < 3)
11351                                 continue;
11352                         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]);
11353                         if (numpoints < 3)
11354                                 continue;
11355                         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]);
11356                         if (numpoints < 3)
11357                                 continue;
11358                         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]);
11359                         if (numpoints < 3)
11360                                 continue;
11361                         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]);
11362                         if (numpoints < 3)
11363                                 continue;
11364                         // some part of the triangle survived, so we have to accept it...
11365                         if (dynamic)
11366                         {
11367                                 // dynamic always uses the original triangle
11368                                 numpoints = 3;
11369                                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11370                                 {
11371                                         index = 3*e[cornerindex];
11372                                         VectorCopy(vertex3f + index, v[cornerindex]);
11373                                 }
11374                         }
11375                         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11376                         {
11377                                 // convert vertex positions to texcoords
11378                                 Matrix4x4_Transform(&projection, v[cornerindex], temp);
11379                                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11380                                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11381                                 // calculate distance fade from the projection origin
11382                                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11383                                 f = bound(0.0f, f, 1.0f);
11384                                 c[cornerindex][0] = r * f;
11385                                 c[cornerindex][1] = g * f;
11386                                 c[cornerindex][2] = b * f;
11387                                 c[cornerindex][3] = 1.0f;
11388                                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11389                         }
11390                         if (dynamic)
11391                                 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);
11392                         else
11393                                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11394                                         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);
11395                 }
11396         }
11397 }
11398
11399 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11400 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)
11401 {
11402         int renderentityindex;
11403         float worldmins[3];
11404         float worldmaxs[3];
11405         entity_render_t *ent;
11406
11407         if (!cl_decals_newsystem.integer)
11408                 return;
11409
11410         worldmins[0] = worldorigin[0] - worldsize;
11411         worldmins[1] = worldorigin[1] - worldsize;
11412         worldmins[2] = worldorigin[2] - worldsize;
11413         worldmaxs[0] = worldorigin[0] + worldsize;
11414         worldmaxs[1] = worldorigin[1] + worldsize;
11415         worldmaxs[2] = worldorigin[2] + worldsize;
11416
11417         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11418
11419         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11420         {
11421                 ent = r_refdef.scene.entities[renderentityindex];
11422                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11423                         continue;
11424
11425                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11426         }
11427 }
11428
11429 typedef struct r_decalsystem_splatqueue_s
11430 {
11431         vec3_t worldorigin;
11432         vec3_t worldnormal;
11433         float color[4];
11434         float tcrange[4];
11435         float worldsize;
11436         int decalsequence;
11437 }
11438 r_decalsystem_splatqueue_t;
11439
11440 int r_decalsystem_numqueued = 0;
11441 #define MAX_DECALSYSTEM_QUEUE 1024
11442 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11443
11444 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)
11445 {
11446         r_decalsystem_splatqueue_t *queue;
11447
11448         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11449                 return;
11450
11451         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11452         VectorCopy(worldorigin, queue->worldorigin);
11453         VectorCopy(worldnormal, queue->worldnormal);
11454         Vector4Set(queue->color, r, g, b, a);
11455         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11456         queue->worldsize = worldsize;
11457         queue->decalsequence = cl.decalsequence++;
11458 }
11459
11460 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11461 {
11462         int i;
11463         r_decalsystem_splatqueue_t *queue;
11464
11465         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11466                 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);
11467         r_decalsystem_numqueued = 0;
11468 }
11469
11470 extern cvar_t cl_decals_max;
11471 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11472 {
11473         int i;
11474         decalsystem_t *decalsystem = &ent->decalsystem;
11475         int numdecals;
11476         int killsequence;
11477         tridecal_t *decal;
11478         float frametime;
11479         float lifetime;
11480
11481         if (!decalsystem->numdecals)
11482                 return;
11483
11484         if (r_showsurfaces.integer)
11485                 return;
11486
11487         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11488         {
11489                 R_DecalSystem_Reset(decalsystem);
11490                 return;
11491         }
11492
11493         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11494         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11495
11496         if (decalsystem->lastupdatetime)
11497                 frametime = (cl.time - decalsystem->lastupdatetime);
11498         else
11499                 frametime = 0;
11500         decalsystem->lastupdatetime = cl.time;
11501         decal = decalsystem->decals;
11502         numdecals = decalsystem->numdecals;
11503
11504         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11505         {
11506                 if (decal->color4ub[0][3])
11507                 {
11508                         decal->lived += frametime;
11509                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11510                         {
11511                                 memset(decal, 0, sizeof(*decal));
11512                                 if (decalsystem->freedecal > i)
11513                                         decalsystem->freedecal = i;
11514                         }
11515                 }
11516         }
11517         decal = decalsystem->decals;
11518         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
11519                 numdecals--;
11520
11521         // collapse the array by shuffling the tail decals into the gaps
11522         for (;;)
11523         {
11524                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
11525                         decalsystem->freedecal++;
11526                 if (decalsystem->freedecal == numdecals)
11527                         break;
11528                 decal[decalsystem->freedecal] = decal[--numdecals];
11529         }
11530
11531         decalsystem->numdecals = numdecals;
11532
11533         if (numdecals <= 0)
11534         {
11535                 // if there are no decals left, reset decalsystem
11536                 R_DecalSystem_Reset(decalsystem);
11537         }
11538 }
11539
11540 extern skinframe_t *decalskinframe;
11541 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11542 {
11543         int i;
11544         decalsystem_t *decalsystem = &ent->decalsystem;
11545         int numdecals;
11546         tridecal_t *decal;
11547         float fadedelay;
11548         float faderate;
11549         float alpha;
11550         float *v3f;
11551         float *c4f;
11552         float *t2f;
11553         const int *e;
11554         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11555         int numtris = 0;
11556
11557         numdecals = decalsystem->numdecals;
11558         if (!numdecals)
11559                 return;
11560
11561         if (r_showsurfaces.integer)
11562                 return;
11563
11564         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11565         {
11566                 R_DecalSystem_Reset(decalsystem);
11567                 return;
11568         }
11569
11570         // if the model is static it doesn't matter what value we give for
11571         // wantnormals and wanttangents, so this logic uses only rules applicable
11572         // to a model, knowing that they are meaningless otherwise
11573         if (ent == r_refdef.scene.worldentity)
11574                 RSurf_ActiveWorldEntity();
11575         else
11576                 RSurf_ActiveModelEntity(ent, false, false, false);
11577
11578         decalsystem->lastupdatetime = cl.time;
11579         decal = decalsystem->decals;
11580
11581         fadedelay = cl_decals_time.value;
11582         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11583
11584         // update vertex positions for animated models
11585         v3f = decalsystem->vertex3f;
11586         c4f = decalsystem->color4f;
11587         t2f = decalsystem->texcoord2f;
11588         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11589         {
11590                 if (!decal->color4ub[0][3])
11591                         continue;
11592
11593                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11594                         continue;
11595
11596                 // update color values for fading decals
11597                 if (decal->lived >= cl_decals_time.value)
11598                 {
11599                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11600                         alpha *= (1.0f/255.0f);
11601                 }
11602                 else
11603                         alpha = 1.0f/255.0f;
11604
11605                 c4f[ 0] = decal->color4ub[0][0] * alpha;
11606                 c4f[ 1] = decal->color4ub[0][1] * alpha;
11607                 c4f[ 2] = decal->color4ub[0][2] * alpha;
11608                 c4f[ 3] = 1;
11609                 c4f[ 4] = decal->color4ub[1][0] * alpha;
11610                 c4f[ 5] = decal->color4ub[1][1] * alpha;
11611                 c4f[ 6] = decal->color4ub[1][2] * alpha;
11612                 c4f[ 7] = 1;
11613                 c4f[ 8] = decal->color4ub[2][0] * alpha;
11614                 c4f[ 9] = decal->color4ub[2][1] * alpha;
11615                 c4f[10] = decal->color4ub[2][2] * alpha;
11616                 c4f[11] = 1;
11617
11618                 t2f[0] = decal->texcoord2f[0][0];
11619                 t2f[1] = decal->texcoord2f[0][1];
11620                 t2f[2] = decal->texcoord2f[1][0];
11621                 t2f[3] = decal->texcoord2f[1][1];
11622                 t2f[4] = decal->texcoord2f[2][0];
11623                 t2f[5] = decal->texcoord2f[2][1];
11624
11625                 // update vertex positions for animated models
11626                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
11627                 {
11628                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11629                         VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
11630                         VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
11631                         VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
11632                 }
11633                 else
11634                 {
11635                         VectorCopy(decal->vertex3f[0], v3f);
11636                         VectorCopy(decal->vertex3f[1], v3f + 3);
11637                         VectorCopy(decal->vertex3f[2], v3f + 6);
11638                 }
11639
11640                 v3f += 9;
11641                 c4f += 12;
11642                 t2f += 6;
11643                 numtris++;
11644         }
11645
11646         if (numtris > 0)
11647         {
11648                 r_refdef.stats.drawndecals += numtris;
11649
11650                 if (r_refdef.fogenabled)
11651                 {
11652                         switch(vid.renderpath)
11653                         {
11654                         case RENDERPATH_GL20:
11655                         case RENDERPATH_CGGL:
11656                         case RENDERPATH_GL13:
11657                         case RENDERPATH_GL11:
11658                                 for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
11659                                 {
11660                                         alpha = RSurf_FogVertex(v3f);
11661                                         c4f[0] *= alpha;
11662                                         c4f[1] *= alpha;
11663                                         c4f[2] *= alpha;
11664                                 }
11665                                 break;
11666                         }
11667                 }
11668
11669                 // now render the decals all at once
11670                 // (this assumes they all use one particle font texture!)
11671                 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);
11672                 R_Mesh_ResetTextureState();
11673                 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
11674                 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
11675                 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
11676                 GL_DepthMask(false);
11677                 GL_DepthRange(0, 1);
11678                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11679                 GL_DepthTest(true);
11680                 GL_CullFace(GL_NONE);
11681                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11682                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
11683                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
11684         }
11685 }
11686
11687 static void R_DrawModelDecals(void)
11688 {
11689         int i, numdecals;
11690
11691         // fade faster when there are too many decals
11692         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11693         for (i = 0;i < r_refdef.scene.numentities;i++)
11694                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11695
11696         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11697         for (i = 0;i < r_refdef.scene.numentities;i++)
11698                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11699                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11700
11701         R_DecalSystem_ApplySplatEntitiesQueue();
11702
11703         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11704         for (i = 0;i < r_refdef.scene.numentities;i++)
11705                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11706
11707         r_refdef.stats.totaldecals += numdecals;
11708
11709         if (r_showsurfaces.integer)
11710                 return;
11711
11712         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11713
11714         for (i = 0;i < r_refdef.scene.numentities;i++)
11715         {
11716                 if (!r_refdef.viewcache.entityvisible[i])
11717                         continue;
11718                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11719                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11720         }
11721 }
11722
11723 void R_DrawDebugModel(void)
11724 {
11725         entity_render_t *ent = rsurface.entity;
11726         int i, j, k, l, flagsmask;
11727         const int *elements;
11728         q3mbrush_t *brush;
11729         const msurface_t *surface;
11730         dp_model_t *model = ent->model;
11731         vec3_t v;
11732
11733         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11734
11735         R_Mesh_ColorPointer(NULL, 0, 0);
11736         R_Mesh_ResetTextureState();
11737         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11738         GL_DepthRange(0, 1);
11739         GL_DepthTest(!r_showdisabledepthtest.integer);
11740         GL_DepthMask(false);
11741         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11742
11743         if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
11744         {
11745                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11746                 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
11747                 {
11748                         if (brush->colbrushf && brush->colbrushf->numtriangles)
11749                         {
11750                                 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
11751                                 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);
11752                                 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
11753                         }
11754                 }
11755                 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
11756                 {
11757                         if (surface->num_collisiontriangles)
11758                         {
11759                                 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
11760                                 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);
11761                                 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
11762                         }
11763                 }
11764         }
11765
11766         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11767
11768         if (r_showtris.integer || r_shownormals.integer)
11769         {
11770                 if (r_showdisabledepthtest.integer)
11771                 {
11772                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11773                         GL_DepthMask(false);
11774                 }
11775                 else
11776                 {
11777                         GL_BlendFunc(GL_ONE, GL_ZERO);
11778                         GL_DepthMask(true);
11779                 }
11780                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11781                 {
11782                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11783                                 continue;
11784                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11785                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11786                         {
11787                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
11788                                 if (r_showtris.value > 0)
11789                                 {
11790                                         if (!rsurface.texture->currentlayers->depthmask)
11791                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11792                                         else if (ent == r_refdef.scene.worldentity)
11793                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11794                                         else
11795                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11796                                         elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
11797                                         R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
11798                                         R_Mesh_ColorPointer(NULL, 0, 0);
11799                                         R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
11800                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11801                                         //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
11802                                         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);
11803                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11804                                         CHECKGLERROR
11805                                 }
11806                                 if (r_shownormals.value < 0)
11807                                 {
11808                                         qglBegin(GL_LINES);
11809                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11810                                         {
11811                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11812                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11813                                                 qglVertex3f(v[0], v[1], v[2]);
11814                                                 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
11815                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11816                                                 qglVertex3f(v[0], v[1], v[2]);
11817                                         }
11818                                         qglEnd();
11819                                         CHECKGLERROR
11820                                 }
11821                                 if (r_shownormals.value > 0)
11822                                 {
11823                                         qglBegin(GL_LINES);
11824                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11825                                         {
11826                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11827                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11828                                                 qglVertex3f(v[0], v[1], v[2]);
11829                                                 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
11830                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11831                                                 qglVertex3f(v[0], v[1], v[2]);
11832                                         }
11833                                         qglEnd();
11834                                         CHECKGLERROR
11835                                         qglBegin(GL_LINES);
11836                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11837                                         {
11838                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11839                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11840                                                 qglVertex3f(v[0], v[1], v[2]);
11841                                                 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
11842                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11843                                                 qglVertex3f(v[0], v[1], v[2]);
11844                                         }
11845                                         qglEnd();
11846                                         CHECKGLERROR
11847                                         qglBegin(GL_LINES);
11848                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11849                                         {
11850                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11851                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11852                                                 qglVertex3f(v[0], v[1], v[2]);
11853                                                 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
11854                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11855                                                 qglVertex3f(v[0], v[1], v[2]);
11856                                         }
11857                                         qglEnd();
11858                                         CHECKGLERROR
11859                                 }
11860                         }
11861                 }
11862                 rsurface.texture = NULL;
11863         }
11864 }
11865
11866 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11867 int r_maxsurfacelist = 0;
11868 const msurface_t **r_surfacelist = NULL;
11869 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11870 {
11871         int i, j, endj, f, flagsmask;
11872         texture_t *t;
11873         dp_model_t *model = r_refdef.scene.worldmodel;
11874         msurface_t *surfaces;
11875         unsigned char *update;
11876         int numsurfacelist = 0;
11877         if (model == NULL)
11878                 return;
11879
11880         if (r_maxsurfacelist < model->num_surfaces)
11881         {
11882                 r_maxsurfacelist = model->num_surfaces;
11883                 if (r_surfacelist)
11884                         Mem_Free((msurface_t**)r_surfacelist);
11885                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11886         }
11887
11888         RSurf_ActiveWorldEntity();
11889
11890         surfaces = model->data_surfaces;
11891         update = model->brushq1.lightmapupdateflags;
11892
11893         // update light styles on this submodel
11894         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11895         {
11896                 model_brush_lightstyleinfo_t *style;
11897                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11898                 {
11899                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11900                         {
11901                                 int *list = style->surfacelist;
11902                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11903                                 for (j = 0;j < style->numsurfaces;j++)
11904                                         update[list[j]] = true;
11905                         }
11906                 }
11907         }
11908
11909         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11910
11911         if (debug)
11912         {
11913                 R_DrawDebugModel();
11914                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11915                 return;
11916         }
11917
11918         f = 0;
11919         t = NULL;
11920         rsurface.uselightmaptexture = false;
11921         rsurface.texture = NULL;
11922         rsurface.rtlight = NULL;
11923         numsurfacelist = 0;
11924         // add visible surfaces to draw list
11925         for (i = 0;i < model->nummodelsurfaces;i++)
11926         {
11927                 j = model->sortedmodelsurfaces[i];
11928                 if (r_refdef.viewcache.world_surfacevisible[j])
11929                         r_surfacelist[numsurfacelist++] = surfaces + j;
11930         }
11931         // update lightmaps if needed
11932         if (model->brushq1.firstrender)
11933         {
11934                 model->brushq1.firstrender = false;
11935                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11936                         if (update[j])
11937                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11938         }
11939         else if (update)
11940         {
11941                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11942                         if (r_refdef.viewcache.world_surfacevisible[j])
11943                                 if (update[j])
11944                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11945         }
11946         // don't do anything if there were no surfaces
11947         if (!numsurfacelist)
11948         {
11949                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11950                 return;
11951         }
11952         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11953         GL_AlphaTest(false);
11954
11955         // add to stats if desired
11956         if (r_speeds.integer && !skysurfaces && !depthonly)
11957         {
11958                 r_refdef.stats.world_surfaces += numsurfacelist;
11959                 for (j = 0;j < numsurfacelist;j++)
11960                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11961         }
11962
11963         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11964 }
11965
11966 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11967 {
11968         int i, j, endj, f, flagsmask;
11969         texture_t *t;
11970         dp_model_t *model = ent->model;
11971         msurface_t *surfaces;
11972         unsigned char *update;
11973         int numsurfacelist = 0;
11974         if (model == NULL)
11975                 return;
11976
11977         if (r_maxsurfacelist < model->num_surfaces)
11978         {
11979                 r_maxsurfacelist = model->num_surfaces;
11980                 if (r_surfacelist)
11981                         Mem_Free((msurface_t **)r_surfacelist);
11982                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11983         }
11984
11985         // if the model is static it doesn't matter what value we give for
11986         // wantnormals and wanttangents, so this logic uses only rules applicable
11987         // to a model, knowing that they are meaningless otherwise
11988         if (ent == r_refdef.scene.worldentity)
11989                 RSurf_ActiveWorldEntity();
11990         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11991                 RSurf_ActiveModelEntity(ent, false, false, false);
11992         else if (prepass)
11993                 RSurf_ActiveModelEntity(ent, true, true, true);
11994         else if (depthonly)
11995                 RSurf_ActiveModelEntity(ent, false, false, false);
11996         else
11997         {
11998                 switch (vid.renderpath)
11999                 {
12000                 case RENDERPATH_GL20:
12001                 case RENDERPATH_CGGL:
12002                         RSurf_ActiveModelEntity(ent, true, true, false);
12003                         break;
12004                 case RENDERPATH_GL13:
12005                 case RENDERPATH_GL11:
12006                         RSurf_ActiveModelEntity(ent, true, false, false);
12007                         break;
12008                 }
12009         }
12010
12011         surfaces = model->data_surfaces;
12012         update = model->brushq1.lightmapupdateflags;
12013
12014         // update light styles
12015         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12016         {
12017                 model_brush_lightstyleinfo_t *style;
12018                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12019                 {
12020                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12021                         {
12022                                 int *list = style->surfacelist;
12023                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12024                                 for (j = 0;j < style->numsurfaces;j++)
12025                                         update[list[j]] = true;
12026                         }
12027                 }
12028         }
12029
12030         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12031
12032         if (debug)
12033         {
12034                 R_DrawDebugModel();
12035                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12036                 return;
12037         }
12038
12039         f = 0;
12040         t = NULL;
12041         rsurface.uselightmaptexture = false;
12042         rsurface.texture = NULL;
12043         rsurface.rtlight = NULL;
12044         numsurfacelist = 0;
12045         // add visible surfaces to draw list
12046         for (i = 0;i < model->nummodelsurfaces;i++)
12047                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12048         // don't do anything if there were no surfaces
12049         if (!numsurfacelist)
12050         {
12051                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12052                 return;
12053         }
12054         // update lightmaps if needed
12055         if (update)
12056         {
12057                 int updated = 0;
12058                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12059                 {
12060                         if (update[j])
12061                         {
12062                                 updated++;
12063                                 R_BuildLightMap(ent, surfaces + j);
12064                         }
12065                 }
12066         }
12067         if (update)
12068                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12069                         if (update[j])
12070                                 R_BuildLightMap(ent, surfaces + j);
12071         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12072         GL_AlphaTest(false);
12073
12074         // add to stats if desired
12075         if (r_speeds.integer && !skysurfaces && !depthonly)
12076         {
12077                 r_refdef.stats.entities_surfaces += numsurfacelist;
12078                 for (j = 0;j < numsurfacelist;j++)
12079                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
12080         }
12081
12082         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12083 }
12084
12085 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12086 {
12087         static texture_t texture;
12088         static msurface_t surface;
12089         const msurface_t *surfacelist = &surface;
12090
12091         // fake enough texture and surface state to render this geometry
12092
12093         texture.update_lastrenderframe = -1; // regenerate this texture
12094         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12095         texture.currentskinframe = skinframe;
12096         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12097         texture.specularscalemod = 1;
12098         texture.specularpowermod = 1;
12099
12100         surface.texture = &texture;
12101         surface.num_triangles = numtriangles;
12102         surface.num_firsttriangle = firsttriangle;
12103         surface.num_vertices = numvertices;
12104         surface.num_firstvertex = firstvertex;
12105
12106         // now render it
12107         rsurface.texture = R_GetCurrentTexture(surface.texture);
12108         rsurface.uselightmaptexture = false;
12109         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12110 }
12111
12112 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)
12113 {
12114         static msurface_t surface;
12115         const msurface_t *surfacelist = &surface;
12116
12117         // fake enough texture and surface state to render this geometry
12118
12119         surface.texture = texture;
12120         surface.num_triangles = numtriangles;
12121         surface.num_firsttriangle = firsttriangle;
12122         surface.num_vertices = numvertices;
12123         surface.num_firstvertex = firstvertex;
12124
12125         // now render it
12126         rsurface.texture = R_GetCurrentTexture(surface.texture);
12127         rsurface.uselightmaptexture = false;
12128         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12129 }