]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
Make SHADERPERMUTATION_COUNT be the actual size of the array.
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #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)\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, ivec(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] *= cubecolor;\n"
1365 "       gl_FragData[1] *= 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 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1551 "#define lightcolor LightColor\n"
1552 "#endif // MODE_LIGHTDIRECTION\n"
1553 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1554 "#define SHADING\n"
1555 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1556 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1557 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1558 "       // convert modelspace light vector to tangentspace\n"
1559 "       myhalf3 lightnormal;\n"
1560 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1561 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1562 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1563 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1564 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1565 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1566 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1567 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1568 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1569 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1570 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1571 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1572 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1573 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1574 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1575 "#define SHADING\n"
1576 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1577 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1578 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1579 "#endif\n"
1580 "\n"
1581 "\n"
1582 "\n"
1583 "\n"
1584 "#ifdef MODE_LIGHTMAP\n"
1585 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1586 "#endif // MODE_LIGHTMAP\n"
1587 "#ifdef MODE_VERTEXCOLOR\n"
1588 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1589 "#endif // MODE_VERTEXCOLOR\n"
1590 "#ifdef MODE_FLATCOLOR\n"
1591 "       color.rgb = diffusetex * Color_Ambient;\n"
1592 "#endif // MODE_FLATCOLOR\n"
1593 "\n"
1594 "\n"
1595 "\n"
1596 "\n"
1597 "#ifdef SHADING\n"
1598 "# ifdef USEDIFFUSE\n"
1599 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1600 "#  ifdef USESPECULAR\n"
1601 "#   ifdef USEEXACTSPECULARMATH\n"
1602 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1603 "#   else\n"
1604 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1605 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1606 "#   endif\n"
1607 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
1608 "#  else\n"
1609 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1610 "#  endif\n"
1611 "# else\n"
1612 "       color.rgb = diffusetex * Color_Ambient;\n"
1613 "# endif\n"
1614 "#endif\n"
1615 "\n"
1616 "#ifdef USEDEFERREDLIGHTMAP\n"
1617 "       color.rgb += diffusetex * myhalf3(texture2DRect(Texture_ScreenDiffuse, gl_FragCoord.xy)) * DeferredMod_Diffuse;\n"
1618 "       color.rgb += glosstex * myhalf3(texture2DRect(Texture_ScreenSpecular, gl_FragCoord.xy)) * DeferredMod_Specular;\n"
1619 "#endif\n"
1620 "\n"
1621 "#ifdef USEGLOW\n"
1622 "#ifdef USEVERTEXTEXTUREBLEND\n"
1623 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1624 "#else\n"
1625 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1626 "#endif\n"
1627 "#endif\n"
1628 "\n"
1629 "#ifdef USEFOG\n"
1630 "#ifdef MODE_LIGHTSOURCE\n"
1631 "       color.rgb *= myhalf(FogVertex());\n"
1632 "#else\n"
1633 "       color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1634 "#endif\n"
1635 "#endif\n"
1636 "\n"
1637 "       // 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"
1638 "#ifdef USEREFLECTION\n"
1639 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1640 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1641 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1642 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1643 "       // FIXME temporary hack to detect the case that the reflection\n"
1644 "       // gets blackened at edges due to leaving the area that contains actual\n"
1645 "       // content.\n"
1646 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1647 "       // 'appening.\n"
1648 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1649 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1650 "       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 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1653 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1654 "#endif\n"
1655 "\n"
1656 "       gl_FragColor = vec4(color);\n"
1657 "}\n"
1658 "#endif // FRAGMENT_SHADER\n"
1659 "\n"
1660 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1661 "#endif // !MODE_DEFERREDGEOMETRY\n"
1662 "#endif // !MODE_WATER\n"
1663 "#endif // !MODE_REFRACTION\n"
1664 "#endif // !MODE_BLOOMBLUR\n"
1665 "#endif // !MODE_GENERIC\n"
1666 "#endif // !MODE_POSTPROCESS\n"
1667 "#endif // !MODE_SHOWDEPTH\n"
1668 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1669 ;
1670
1671 /*
1672 =========================================================================================================================================================
1673
1674
1675
1676 =========================================================================================================================================================
1677
1678
1679
1680 =========================================================================================================================================================
1681
1682
1683
1684 =========================================================================================================================================================
1685
1686
1687
1688 =========================================================================================================================================================
1689
1690
1691
1692 =========================================================================================================================================================
1693
1694
1695
1696 =========================================================================================================================================================
1697 */
1698
1699 const char *builtincgshaderstring =
1700 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1701 "// written by Forest 'LordHavoc' Hale\n"
1702 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1703 "\n"
1704 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
1705 "# define USEFOG\n"
1706 "#endif\n"
1707 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1708 "#define USELIGHTMAP\n"
1709 "#endif\n"
1710 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING)\n"
1711 "#define USEEYEVECTOR\n"
1712 "#endif\n"
1713 "\n"
1714 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1715 "#ifdef VERTEX_SHADER\n"
1716 "void main\n"
1717 "(\n"
1718 "float4 gl_Vertex : POSITION,\n"
1719 "uniform float4x4 ModelViewProjectionMatrix,\n"
1720 "out float4 gl_Position : POSITION\n"
1721 ")\n"
1722 "{\n"
1723 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1724 "}\n"
1725 "#endif\n"
1726 "#else // !MODE_DEPTH_ORSHADOW\n"
1727 "\n"
1728 "\n"
1729 "\n"
1730 "\n"
1731 "#ifdef MODE_SHOWDEPTH\n"
1732 "#ifdef VERTEX_SHADER\n"
1733 "void main\n"
1734 "(\n"
1735 "float4 gl_Vertex : POSITION,\n"
1736 "uniform float4x4 ModelViewProjectionMatrix,\n"
1737 "out float4 gl_Position : POSITION,\n"
1738 "out float4 gl_FrontColor : COLOR0\n"
1739 ")\n"
1740 "{\n"
1741 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1742 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1743 "}\n"
1744 "#endif\n"
1745 "\n"
1746 "#ifdef FRAGMENT_SHADER\n"
1747 "void main\n"
1748 "(\n"
1749 "float4 gl_FrontColor : COLOR0,\n"
1750 "out float4 gl_FragColor : COLOR\n"
1751 ")\n"
1752 "{\n"
1753 "       gl_FragColor = gl_FrontColor;\n"
1754 "}\n"
1755 "#endif\n"
1756 "#else // !MODE_SHOWDEPTH\n"
1757 "\n"
1758 "\n"
1759 "\n"
1760 "\n"
1761 "#ifdef MODE_POSTPROCESS\n"
1762 "\n"
1763 "#ifdef VERTEX_SHADER\n"
1764 "void main\n"
1765 "(\n"
1766 "float4 gl_Vertex : POSITION,\n"
1767 "uniform float4x4 ModelViewProjectionMatrix,\n"
1768 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1769 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1770 "out float4 gl_Position : POSITION,\n"
1771 "out float2 TexCoord1 : TEXCOORD0,\n"
1772 "out float2 TexCoord2 : TEXCOORD1\n"
1773 ")\n"
1774 "{\n"
1775 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1776 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1777 "#ifdef USEBLOOM\n"
1778 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1779 "#endif\n"
1780 "}\n"
1781 "#endif\n"
1782 "\n"
1783 "#ifdef FRAGMENT_SHADER\n"
1784 "void main\n"
1785 "(\n"
1786 "float2 TexCoord1 : TEXCOORD0,\n"
1787 "float2 TexCoord2 : TEXCOORD1,\n"
1788 "uniform sampler2D Texture_First,\n"
1789 "#ifdef USEBLOOM\n"
1790 "uniform sampler2D Texture_Second,\n"
1791 "#endif\n"
1792 "#ifdef USEGAMMARAMPS\n"
1793 "uniform sampler2D Texture_GammaRamps,\n"
1794 "#endif\n"
1795 "#ifdef USESATURATION\n"
1796 "uniform float Saturation,\n"
1797 "#endif\n"
1798 "#ifdef USEVIEWTINT\n"
1799 "uniform float4 ViewTintColor,\n"
1800 "#endif\n"
1801 "uniform float4 UserVec1,\n"
1802 "uniform float4 UserVec2,\n"
1803 "uniform float4 UserVec3,\n"
1804 "uniform float4 UserVec4,\n"
1805 "uniform float ClientTime,\n"
1806 "uniform float2 PixelSize,\n"
1807 "out float4 gl_FragColor : COLOR\n"
1808 ")\n"
1809 "{\n"
1810 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1811 "#ifdef USEBLOOM\n"
1812 "       gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
1813 "#endif\n"
1814 "#ifdef USEVIEWTINT\n"
1815 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1816 "#endif\n"
1817 "\n"
1818 "#ifdef USEPOSTPROCESSING\n"
1819 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1820 "// 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"
1821 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1822 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1823 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1824 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
1825 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
1826 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
1827 "#endif\n"
1828 "\n"
1829 "#ifdef USESATURATION\n"
1830 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
1831 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
1832 "       //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
1833 "       gl_FragColor.rgb = mix(float3(y), gl_FragColor.rgb, Saturation);\n"
1834 "#endif\n"
1835 "\n"
1836 "#ifdef USEGAMMARAMPS\n"
1837 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
1838 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
1839 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
1840 "#endif\n"
1841 "}\n"
1842 "#endif\n"
1843 "#else // !MODE_POSTPROCESS\n"
1844 "\n"
1845 "\n"
1846 "\n"
1847 "\n"
1848 "#ifdef MODE_GENERIC\n"
1849 "#ifdef VERTEX_SHADER\n"
1850 "void main\n"
1851 "(\n"
1852 "float4 gl_Vertex : POSITION,\n"
1853 "uniform float4x4 ModelViewProjectionMatrix,\n"
1854 "float4 gl_Color : COLOR0,\n"
1855 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1856 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1857 "out float4 gl_Position : POSITION,\n"
1858 "out float4 gl_FrontColor : COLOR,\n"
1859 "out float2 TexCoord1 : TEXCOORD0,\n"
1860 "out float2 TexCoord2 : TEXCOORD1\n"
1861 ")\n"
1862 "{\n"
1863 "       gl_FrontColor = gl_Color;\n"
1864 "#ifdef USEDIFFUSE\n"
1865 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1866 "#endif\n"
1867 "#ifdef USESPECULAR\n"
1868 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1869 "#endif\n"
1870 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1871 "}\n"
1872 "#endif\n"
1873 "\n"
1874 "#ifdef FRAGMENT_SHADER\n"
1875 "\n"
1876 "void main\n"
1877 "(\n"
1878 "float4 gl_FrontColor : COLOR,\n"
1879 "float2 TexCoord1 : TEXCOORD0,\n"
1880 "float2 TexCoord2 : TEXCOORD1,\n"
1881 "#ifdef USEDIFFUSE\n"
1882 "uniform sampler2D Texture_First,\n"
1883 "#endif\n"
1884 "#ifdef USESPECULAR\n"
1885 "uniform sampler2D Texture_Second,\n"
1886 "#endif\n"
1887 "out float4 gl_FragColor : COLOR\n"
1888 ")\n"
1889 "{\n"
1890 "       gl_FragColor = gl_FrontColor;\n"
1891 "#ifdef USEDIFFUSE\n"
1892 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
1893 "#endif\n"
1894 "\n"
1895 "#ifdef USESPECULAR\n"
1896 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
1897 "# ifdef USECOLORMAPPING\n"
1898 "       gl_FragColor *= tex2;\n"
1899 "# endif\n"
1900 "# ifdef USEGLOW\n"
1901 "       gl_FragColor += tex2;\n"
1902 "# endif\n"
1903 "# ifdef USEVERTEXTEXTUREBLEND\n"
1904 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
1905 "# endif\n"
1906 "#endif\n"
1907 "}\n"
1908 "#endif\n"
1909 "#else // !MODE_GENERIC\n"
1910 "\n"
1911 "\n"
1912 "\n"
1913 "\n"
1914 "#ifdef MODE_BLOOMBLUR\n"
1915 "#ifdef VERTEX_SHADER\n"
1916 "void main\n"
1917 "(\n"
1918 "float4 gl_Vertex : POSITION,\n"
1919 "uniform float4x4 ModelViewProjectionMatrix,\n"
1920 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1921 "out float4 gl_Position : POSITION,\n"
1922 "out float2 TexCoord : TEXCOORD0\n"
1923 ")\n"
1924 "{\n"
1925 "       TexCoord = gl_MultiTexCoord0.xy;\n"
1926 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1927 "}\n"
1928 "#endif\n"
1929 "\n"
1930 "#ifdef FRAGMENT_SHADER\n"
1931 "\n"
1932 "void main\n"
1933 "(\n"
1934 "float2 TexCoord : TEXCOORD0,\n"
1935 "uniform sampler2D Texture_First,\n"
1936 "uniform float4 BloomBlur_Parameters,\n"
1937 "out float4 gl_FragColor : COLOR\n"
1938 ")\n"
1939 "{\n"
1940 "       int i;\n"
1941 "       float2 tc = TexCoord;\n"
1942 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
1943 "       tc += BloomBlur_Parameters.xy;\n"
1944 "       for (i = 1;i < SAMPLES;i++)\n"
1945 "       {\n"
1946 "               color += tex2D(Texture_First, tc).rgb;\n"
1947 "               tc += BloomBlur_Parameters.xy;\n"
1948 "       }\n"
1949 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
1950 "}\n"
1951 "#endif\n"
1952 "#else // !MODE_BLOOMBLUR\n"
1953 "#ifdef MODE_REFRACTION\n"
1954 "#ifdef VERTEX_SHADER\n"
1955 "void main\n"
1956 "(\n"
1957 "float4 gl_Vertex : POSITION,\n"
1958 "uniform float4x4 ModelViewProjectionMatrix,\n"
1959 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1960 "uniform mat4 TexMatrix,\n"
1961 "uniform float3 EyePosition,\n"
1962 "out float4 gl_Position : POSITION,\n"
1963 "out float2 TexCoord : TEXCOORD0,\n"
1964 "out float3 EyeVector : TEXCOORD1,\n"
1965 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
1966 ")\n"
1967 "{\n"
1968 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
1969 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1970 "       ModelViewProjectionPosition = gl_Position;\n"
1971 "}\n"
1972 "#endif\n"
1973 "\n"
1974 "#ifdef FRAGMENT_SHADER\n"
1975 "void main\n"
1976 "(\n"
1977 "float2 TexCoord : TEXCOORD0,\n"
1978 "float3 EyeVector : TEXCOORD1,\n"
1979 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
1980 "uniform sampler2D Texture_Normal,\n"
1981 "uniform sampler2D Texture_Refraction,\n"
1982 "uniform sampler2D Texture_Reflection,\n"
1983 "uniform float4 DistortScaleRefractReflect,\n"
1984 "uniform float4 ScreenScaleRefractReflect,\n"
1985 "uniform float4 ScreenCenterRefractReflect,\n"
1986 "uniform float4 RefractColor,\n"
1987 "out float4 gl_FragColor : COLOR\n"
1988 ")\n"
1989 "{\n"
1990 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
1991 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1992 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1993 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
1994 "       // FIXME temporary hack to detect the case that the reflection\n"
1995 "       // gets blackened at edges due to leaving the area that contains actual\n"
1996 "       // content.\n"
1997 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1998 "       // 'appening.\n"
1999 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2000 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2001 "       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 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2004 "       gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2005 "}\n"
2006 "#endif\n"
2007 "#else // !MODE_REFRACTION\n"
2008 "\n"
2009 "\n"
2010 "\n"
2011 "\n"
2012 "#ifdef MODE_WATER\n"
2013 "#ifdef VERTEX_SHADER\n"
2014 "\n"
2015 "void main\n"
2016 "(\n"
2017 "float4 gl_Vertex : POSITION,\n"
2018 "uniform float4x4 ModelViewProjectionMatrix,\n"
2019 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2020 "uniform mat4 TexMatrix,\n"
2021 "uniform float3 EyePosition,\n"
2022 "out float4 gl_Position : POSITION,\n"
2023 "out float2 TexCoord : TEXCOORD0,\n"
2024 "out float3 EyeVector : TEXCOORD1,\n"
2025 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2026 ")\n"
2027 "{\n"
2028 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2029 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2030 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2031 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2032 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2033 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2034 "       ModelViewProjectionPosition = gl_Position;\n"
2035 "}\n"
2036 "#endif\n"
2037 "\n"
2038 "#ifdef FRAGMENT_SHADER\n"
2039 "void main\n"
2040 "(\n"
2041 "float2 TexCoord : TEXCOORD0,\n"
2042 "float3 EyeVector : TEXCOORD1,\n"
2043 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2044 "uniform sampler2D Texture_Normal,\n"
2045 "uniform sampler2D Texture_Refraction,\n"
2046 "uniform sampler2D Texture_Reflection,\n"
2047 "uniform float4 DistortScaleRefractReflect,\n"
2048 "uniform float4 ScreenScaleRefractReflect,\n"
2049 "uniform float4 ScreenCenterRefractReflect,\n"
2050 "uniform float4 RefractColor,\n"
2051 "uniform float4 ReflectColor,\n"
2052 "uniform float ReflectFactor,\n"
2053 "uniform float ReflectOffset,\n"
2054 "out float4 gl_FragColor : COLOR\n"
2055 ")\n"
2056 "{\n"
2057 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2058 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2059 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2060 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xyxy * DistortScaleRefractReflect;\n"
2061 "       // FIXME temporary hack to detect the case that the reflection\n"
2062 "       // gets blackened at edges due to leaving the area that contains actual\n"
2063 "       // content.\n"
2064 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2065 "       // 'appening.\n"
2066 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2067 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2068 "       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 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2071 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2072 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\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 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2076 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2077 "       gl_FragColor = mix(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2078 "}\n"
2079 "#endif\n"
2080 "#else // !MODE_WATER\n"
2081 "\n"
2082 "\n"
2083 "\n"
2084 "\n"
2085 "// 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"
2086 "\n"
2087 "// fragment shader specific:\n"
2088 "#ifdef FRAGMENT_SHADER\n"
2089 "\n"
2090 "#ifdef USEFOG\n"
2091 "float FogVertex(float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask)\n"
2092 "{\n"
2093 "       float fogfrac;\n"
2094 "#ifdef USEFOGOUTSIDE\n"
2095 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2096 "#else\n"
2097 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2098 "#endif\n"
2099 "       return float(tex2D(Texture_FogMask, half2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
2100 "}\n"
2101 "#endif\n"
2102 "\n"
2103 "#ifdef USEOFFSETMAPPING\n"
2104 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler2D Texture_Normal)\n"
2105 "{\n"
2106 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2107 "       // 14 sample relief mapping: linear search and then binary search\n"
2108 "       // this basically steps forward a small amount repeatedly until it finds\n"
2109 "       // itself inside solid, then jitters forward and back using decreasing\n"
2110 "       // amounts to find the impact\n"
2111 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2112 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2113 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2114 "       float3 RT = float3(TexCoord, 1);\n"
2115 "       OffsetVector *= 0.1;\n"
2116 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2117 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2118 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2119 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2120 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\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)          - 0.5);\n"
2126 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2127 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2128 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2129 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2130 "       return RT.xy;\n"
2131 "#else\n"
2132 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2133 "       // this basically moves forward the full distance, and then backs up based\n"
2134 "       // on height of samples\n"
2135 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2136 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2137 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2138 "       TexCoord += OffsetVector;\n"
2139 "       OffsetVector *= 0.333;\n"
2140 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2141 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2142 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2143 "       return TexCoord;\n"
2144 "#endif\n"
2145 "}\n"
2146 "#endif // USEOFFSETMAPPING\n"
2147 "\n"
2148 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2149 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2150 "# ifndef USESHADOWMAPVSDCT\n"
2151 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2152 "{\n"
2153 "       float3 adir = abs(dir);\n"
2154 "       float2 tc;\n"
2155 "       float2 offset;\n"
2156 "       float ma;\n"
2157 "       if (adir.x > adir.y)\n"
2158 "       {\n"
2159 "               if (adir.x > adir.z) // X\n"
2160 "               {\n"
2161 "                       ma = adir.x;\n"
2162 "                       tc = dir.zy;\n"
2163 "                       offset = float2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
2164 "               }\n"
2165 "               else // Z\n"
2166 "               {\n"
2167 "                       ma = adir.z;\n"
2168 "                       tc = dir.xy;\n"
2169 "                       offset = float2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
2170 "               }\n"
2171 "       }\n"
2172 "       else\n"
2173 "       {\n"
2174 "               if (adir.y > adir.z) // Y\n"
2175 "               {\n"
2176 "                       ma = adir.y;\n"
2177 "                       tc = dir.xz;\n"
2178 "                       offset = float2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
2179 "               }\n"
2180 "               else // Z\n"
2181 "               {\n"
2182 "                       ma = adir.z;\n"
2183 "                       tc = dir.xy;\n"
2184 "                       offset = float2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
2185 "               }\n"
2186 "       }\n"
2187 "\n"
2188 "       float3 stc = float3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2189 "       stc.xy += offset * ShadowMap_Parameters.y;\n"
2190 "       stc.z += ShadowMap_Parameters.z;\n"
2191 "       return stc;\n"
2192 "}\n"
2193 "# else\n"
2194 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2195 "{\n"
2196 "       float3 adir = abs(dir);\n"
2197 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2198 "       float ma = max(max(adir.x, adir.y), adir.z);\n"
2199 "       float3 stc = float3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2200 "       stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
2201 "       stc.z += ShadowMap_Parameters.z;\n"
2202 "       return stc;\n"
2203 "}\n"
2204 "# endif\n"
2205 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2206 "\n"
2207 "#ifdef USESHADOWMAPCUBE\n"
2208 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2209 "{\n"
2210 "    float3 adir = abs(dir);\n"
2211 "    return float4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
2212 "}\n"
2213 "#endif\n"
2214 "\n"
2215 "# ifdef USESHADOWMAPRECT\n"
2216 "#ifdef USESHADOWMAPVSDCT\n"
2217 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2218 "#else\n"
2219 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2220 "#endif\n"
2221 "{\n"
2222 "#ifdef USESHADOWMAPVSDCT\n"
2223 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2224 "#else\n"
2225 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2226 "#endif\n"
2227 "       float f;\n"
2228 "#  ifdef USESHADOWSAMPLER\n"
2229 "\n"
2230 "#    ifdef USESHADOWMAPPCF\n"
2231 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2232 "    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"
2233 "#    else\n"
2234 "    f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2235 "#    endif\n"
2236 "\n"
2237 "#  else\n"
2238 "\n"
2239 "#    ifdef USESHADOWMAPPCF\n"
2240 "#      if USESHADOWMAPPCF > 1\n"
2241 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2242 "    float2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
2243 "    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"
2244 "    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"
2245 "    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"
2246 "    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"
2247 "    float4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
2248 "    f = dot(mix(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2249 "#      else\n"
2250 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2251 "    float2 offset = fract(shadowmaptc.xy);\n"
2252 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2253 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2254 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2255 "    float3 cols = row2 + mix(row1, row3, offset.y);\n"
2256 "    f = dot(mix(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2257 "#      endif\n"
2258 "#    else\n"
2259 "    f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2260 "#    endif\n"
2261 "\n"
2262 "#  endif\n"
2263 "       return f;\n"
2264 "}\n"
2265 "# endif\n"
2266 "\n"
2267 "# ifdef USESHADOWMAP2D\n"
2268 "#ifdef USESHADOWMAPVSDCT\n"
2269 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2270 "#else\n"
2271 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2272 "#endif\n"
2273 "{\n"
2274 "#ifdef USESHADOWMAPVSDCT\n"
2275 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2276 "#else\n"
2277 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2278 "#endif\n"
2279 "    float f;\n"
2280 "\n"
2281 "#  ifdef USESHADOWSAMPLER\n"
2282 "#    ifdef USESHADOWMAPPCF\n"
2283 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, float3(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
2284 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2285 "    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"
2286 "#    else\n"
2287 "    f = shadow2D(Texture_ShadowMap2D, float3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
2288 "#    endif\n"
2289 "#  else\n"
2290 "#    ifdef USESHADOWMAPPCF\n"
2291 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2292 "#      ifdef GL_ARB_texture_gather\n"
2293 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
2294 "#      else\n"
2295 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x,y)*ShadowMap_TextureScale)\n"
2296 "#      endif\n"
2297 "    float2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
2298 "    center *= ShadowMap_TextureScale;\n"
2299 "    float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2300 "    float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2301 "    float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2302 "    float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2303 "    float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2304 "                mix(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2305 "    f = dot(mix(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2306 "#     else\n"
2307 "#      ifdef GL_EXT_gpu_shader4\n"
2308 "#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, ifloat2(x, y)).r\n"
2309 "#      else\n"
2310 "#        define texval(x, y) tex2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
2311 "#      endif\n"
2312 "#      if USESHADOWMAPPCF > 1\n"
2313 "    float2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
2314 "    center *= ShadowMap_TextureScale;\n"
2315 "    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"
2316 "    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"
2317 "    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"
2318 "    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"
2319 "    float4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
2320 "    f = dot(mix(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2321 "#      else\n"
2322 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
2323 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2324 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2325 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2326 "    float3 cols = row2 + mix(row1, row3, offset.y);\n"
2327 "    f = dot(mix(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2328 "#      endif\n"
2329 "#     endif\n"
2330 "#    else\n"
2331 "    f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2332 "#    endif\n"
2333 "#  endif\n"
2334 "    return f;\n"
2335 "}\n"
2336 "# endif\n"
2337 "\n"
2338 "# ifdef USESHADOWMAPCUBE\n"
2339 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2340 "{\n"
2341 "    // apply depth texture cubemap as light filter\n"
2342 "    float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2343 "    float f;\n"
2344 "#  ifdef USESHADOWSAMPLER\n"
2345 "    f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2346 "#  else\n"
2347 "    f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2348 "#  endif\n"
2349 "    return f;\n"
2350 "}\n"
2351 "# endif\n"
2352 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2353 "#endif // FRAGMENT_SHADER\n"
2354 "\n"
2355 "\n"
2356 "\n"
2357 "\n"
2358 "#ifdef MODE_DEFERREDGEOMETRY\n"
2359 "#ifdef VERTEX_SHADER\n"
2360 "void main\n"
2361 "(\n"
2362 "float4 gl_Vertex : POSITION,\n"
2363 "uniform float4x4 ModelViewProjectionMatrix,\n"
2364 "#ifdef USEVERTEXTEXTUREBLEND\n"
2365 "float4 gl_Color : COLOR0,\n"
2366 "#endif\n"
2367 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2368 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2369 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2370 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2371 "uniform mat4 TexMatrix,\n"
2372 "#ifdef USEVERTEXTEXTUREBLEND\n"
2373 "uniform mat4 BackgroundTexMatrix,\n"
2374 "#endif\n"
2375 "uniform mat4 ModelViewMatrix,\n"
2376 "out float4 gl_Position : POSITION,\n"
2377 "out float4 gl_FrontColor : COLOR,\n"
2378 "out float4 TexCoordBoth : TEXCOORD0,\n"
2379 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2380 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2381 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2382 ")\n"
2383 "{\n"
2384 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2385 "#ifdef USEVERTEXTEXTUREBLEND\n"
2386 "       gl_FrontColor = gl_Color;\n"
2387 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2388 "#endif\n"
2389 "\n"
2390 "       // transform unnormalized eye direction into tangent space\n"
2391 "#ifdef USEOFFSETMAPPING\n"
2392 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2393 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2394 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2395 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2396 "#endif\n"
2397 "\n"
2398 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2399 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2400 "       VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2401 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2402 "}\n"
2403 "#endif // VERTEX_SHADER\n"
2404 "\n"
2405 "#ifdef FRAGMENT_SHADER\n"
2406 "void main\n"
2407 "(\n"
2408 "float4 TexCoordBoth : TEXCOORD0,\n"
2409 "float3 EyeVector : TEXCOORD2,\n"
2410 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2411 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2412 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2413 "uniform sampler2D Texture_Normal,\n"
2414 "#ifdef USEALPHAKILL\n"
2415 "uniform sampler2D Texture_Color,\n"
2416 "#endif\n"
2417 "#ifdef USEVERTEXTEXTUREBLEND\n"
2418 "uniform sampler2D Texture_SecondaryNormal,\n"
2419 "#endif\n"
2420 "#ifdef USEOFFSETMAPPING\n"
2421 "uniform float OffsetMapping_Scale,\n"
2422 "#endif\n"
2423 "uniform half SpecularPower,\n"
2424 "out float4 gl_FragColor : COLOR\n"
2425 ")\n"
2426 "{\n"
2427 "       float2 TexCoord = TexCoordBoth.xy;\n"
2428 "#ifdef USEOFFSETMAPPING\n"
2429 "       // apply offsetmapping\n"
2430 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2431 "#define TexCoord TexCoordOffset\n"
2432 "#endif\n"
2433 "\n"
2434 "#ifdef USEALPHAKILL\n"
2435 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2436 "               discard;\n"
2437 "#endif\n"
2438 "\n"
2439 "#ifdef USEVERTEXTEXTUREBLEND\n"
2440 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2441 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2442 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2443 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2444 "#endif\n"
2445 "\n"
2446 "#ifdef USEVERTEXTEXTUREBLEND\n"
2447 "       float3 surfacenormal = mix(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
2448 "#else\n"
2449 "       float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
2450 "#endif\n"
2451 "\n"
2452 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), 1);\n"
2453 "}\n"
2454 "#endif // FRAGMENT_SHADER\n"
2455 "#else // !MODE_DEFERREDGEOMETRY\n"
2456 "\n"
2457 "\n"
2458 "\n"
2459 "\n"
2460 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2461 "#ifdef VERTEX_SHADER\n"
2462 "void main\n"
2463 "(\n"
2464 "float4 gl_Vertex : POSITION,\n"
2465 "uniform float4x4 ModelViewProjectionMatrix,\n"
2466 "uniform mat4 ModelViewMatrix,\n"
2467 "out float4 gl_Position : POSITION,\n"
2468 "out float4 ModelViewPosition : TEXCOORD0\n"
2469 ")\n"
2470 "{\n"
2471 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2472 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2473 "}\n"
2474 "#endif // VERTEX_SHADER\n"
2475 "\n"
2476 "#ifdef FRAGMENT_SHADER\n"
2477 "void main\n"
2478 "(\n"
2479 "float2 Pixel : WPOS,\n"
2480 "float4 ModelViewPosition : TEXCOORD0,\n"
2481 "uniform mat4 ViewToLight,\n"
2482 "uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2483 "uniform float3 LightPosition,\n"
2484 "uniform half3 DeferredColor_Ambient,\n"
2485 "uniform half3 DeferredColor_Diffuse,\n"
2486 "#ifdef USESPECULAR\n"
2487 "uniform half3 DeferredColor_Specular,\n"
2488 "uniform half SpecularPower,\n"
2489 "#endif\n"
2490 "uniform sampler2D Texture_Attenuation,\n"
2491 "uniform samplerRECT Texture_ScreenDepth,\n"
2492 "uniform samplerRECT Texture_ScreenNormalMap,\n"
2493 "\n"
2494 "#ifdef USESHADOWMAPRECT\n"
2495 "# ifdef USESHADOWSAMPLER\n"
2496 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2497 "# else\n"
2498 "uniform samplerRECT Texture_ShadowMapRect,\n"
2499 "# endif\n"
2500 "#endif\n"
2501 "\n"
2502 "#ifdef USESHADOWMAP2D\n"
2503 "# ifdef USESHADOWSAMPLER\n"
2504 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2505 "# else\n"
2506 "uniform sampler2D Texture_ShadowMap2D,\n"
2507 "# endif\n"
2508 "#endif\n"
2509 "\n"
2510 "#ifdef USESHADOWMAPVSDCT\n"
2511 "uniform samplerCUBE Texture_CubeProjection,\n"
2512 "#endif\n"
2513 "\n"
2514 "#ifdef USESHADOWMAPCUBE\n"
2515 "# ifdef USESHADOWSAMPLER\n"
2516 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2517 "# else\n"
2518 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2519 "# endif\n"
2520 "#endif\n"
2521 "\n"
2522 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2523 "uniform float2 ShadowMap_TextureScale,\n"
2524 "uniform float4 ShadowMap_Parameters,\n"
2525 "#endif\n"
2526 "\n"
2527 "out float4 gl_FragData0 : COLOR0,\n"
2528 "out float4 gl_FragData1 : COLOR1\n"
2529 ")\n"
2530 "{\n"
2531 "       // calculate viewspace pixel position\n"
2532 "       float3 position;\n"
2533 "       position.z = ScreenToDepth.y / (texRECT(Texture_ScreenDepth, Pixel).r + ScreenToDepth.x);\n"
2534 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2535 "       // decode viewspace pixel normal\n"
2536 "       half4 normalmap = texRECT(Texture_ScreenNormalMap, Pixel);\n"
2537 "       half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
2538 "       // surfacenormal = pixel normal in viewspace\n"
2539 "       // LightVector = pixel to light in viewspace\n"
2540 "       // CubeVector = position in lightspace\n"
2541 "       // eyevector = pixel to view in viewspace\n"
2542 "       float3 CubeVector = float3(mul(ViewToLight, float4(position,1)));\n"
2543 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2544 "#ifdef USEDIFFUSE\n"
2545 "       // calculate diffuse shading\n"
2546 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2547 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2548 "#endif\n"
2549 "#ifdef USESPECULAR\n"
2550 "       // calculate directional shading\n"
2551 "       float3 eyevector = position * -1.0;\n"
2552 "#  ifdef USEEXACTSPECULARMATH\n"
2553 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
2554 "#  else\n"
2555 "       half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
2556 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
2557 "#  endif\n"
2558 "#endif\n"
2559 "\n"
2560 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2561 "       fade *= ShadowMapCompare(CubeVector,\n"
2562 "# if defined(USESHADOWMAP2D)\n"
2563 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2564 "# endif\n"
2565 "# if defined(USESHADOWMAPRECT)\n"
2566 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2567 "# endif\n"
2568 "# if defined(USESHADOWMAPCUBE)\n"
2569 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2570 "# endif\n"
2571 "\n"
2572 "#ifdef USESHADOWMAPVSDCT\n"
2573 ", Texture_CubeProjection\n"
2574 "#endif\n"
2575 "       );\n"
2576 "#endif\n"
2577 "\n"
2578 "#ifdef USEDIFFUSE\n"
2579 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2580 "#else\n"
2581 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2582 "#endif\n"
2583 "#ifdef USESPECULAR\n"
2584 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2585 "#else\n"
2586 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2587 "#endif\n"
2588 "\n"
2589 "# ifdef USECUBEFILTER\n"
2590 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2591 "       gl_FragData0.rgb *= cubecolor;\n"
2592 "       gl_FragData1.rgb *= cubecolor;\n"
2593 "# endif\n"
2594 "}\n"
2595 "#endif // FRAGMENT_SHADER\n"
2596 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2597 "\n"
2598 "\n"
2599 "\n"
2600 "\n"
2601 "#ifdef VERTEX_SHADER\n"
2602 "void main\n"
2603 "(\n"
2604 "float4 gl_Vertex : POSITION,\n"
2605 "uniform float4x4 ModelViewProjectionMatrix,\n"
2606 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2607 "float4 gl_Color : COLOR0,\n"
2608 "#endif\n"
2609 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2610 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2611 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2612 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2613 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2614 "\n"
2615 "uniform float3 EyePosition,\n"
2616 "uniform mat4 TexMatrix,\n"
2617 "#ifdef USEVERTEXTEXTUREBLEND\n"
2618 "uniform mat4 BackgroundTexMatrix,\n"
2619 "#endif\n"
2620 "#ifdef MODE_LIGHTSOURCE\n"
2621 "uniform mat4 ModelToLight,\n"
2622 "#endif\n"
2623 "#ifdef MODE_LIGHTSOURCE\n"
2624 "uniform float3 LightPosition,\n"
2625 "#endif\n"
2626 "#ifdef MODE_LIGHTDIRECTION\n"
2627 "uniform float3 LightDir,\n"
2628 "#endif\n"
2629 "uniform float4 FogPlane,\n"
2630 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2631 "uniform float3 LightPosition,\n"
2632 "#endif\n"
2633 "\n"
2634 "out float4 gl_FrontColor : COLOR,\n"
2635 "out float4 TexCoordBoth : TEXCOORD0,\n"
2636 "#ifdef USELIGHTMAP\n"
2637 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2638 "#endif\n"
2639 "#ifdef USEEYEVECTOR\n"
2640 "out float3 EyeVector : TEXCOORD2,\n"
2641 "#endif\n"
2642 "#ifdef USEREFLECTION\n"
2643 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2644 "#endif\n"
2645 "#ifdef USEFOG\n"
2646 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2647 "#endif\n"
2648 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2649 "out float3 LightVector : TEXCOORD5,\n"
2650 "#endif\n"
2651 "#ifdef MODE_LIGHTSOURCE\n"
2652 "out float3 CubeVector : TEXCOORD3,\n"
2653 "#endif\n"
2654 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
2655 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2656 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2657 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2658 "#endif\n"
2659 "out float4 gl_Position : POSITION\n"
2660 ")\n"
2661 "{\n"
2662 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2663 "       gl_FrontColor = gl_Color;\n"
2664 "#endif\n"
2665 "       // copy the surface texcoord\n"
2666 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2667 "#ifdef USEVERTEXTEXTUREBLEND\n"
2668 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2669 "#endif\n"
2670 "#ifdef USELIGHTMAP\n"
2671 "       TexCoordLightmap = float2(gl_MultiTexCoord4);\n"
2672 "#endif\n"
2673 "\n"
2674 "#ifdef MODE_LIGHTSOURCE\n"
2675 "       // transform vertex position into light attenuation/cubemap space\n"
2676 "       // (-1 to +1 across the light box)\n"
2677 "       CubeVector = float3(mul(ModelToLight, gl_Vertex));\n"
2678 "\n"
2679 "# ifdef USEDIFFUSE\n"
2680 "       // transform unnormalized light direction into tangent space\n"
2681 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2682 "       //  normalize it per pixel)\n"
2683 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2684 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2685 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2686 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2687 "# endif\n"
2688 "#endif\n"
2689 "\n"
2690 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2691 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2692 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2693 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2694 "#endif\n"
2695 "\n"
2696 "       // transform unnormalized eye direction into tangent space\n"
2697 "#ifdef USEEYEVECTOR\n"
2698 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2699 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2700 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2701 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2702 "#endif\n"
2703 "\n"
2704 "#ifdef USEFOG\n"
2705 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2706 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2707 "#endif\n"
2708 "\n"
2709 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2710 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2711 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2712 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2713 "#endif\n"
2714 "\n"
2715 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2716 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2717 "\n"
2718 "#ifdef USEREFLECTION\n"
2719 "       ModelViewProjectionPosition = gl_Position;\n"
2720 "#endif\n"
2721 "}\n"
2722 "#endif // VERTEX_SHADER\n"
2723 "\n"
2724 "\n"
2725 "\n"
2726 "\n"
2727 "#ifdef FRAGMENT_SHADER\n"
2728 "void main\n"
2729 "(\n"
2730 "#ifdef USEDEFERREDLIGHTMAP\n"
2731 "float2 Pixel : WPOS,\n"
2732 "#endif\n"
2733 "float4 gl_FrontColor : COLOR,\n"
2734 "float4 TexCoordBoth : TEXCOORD0,\n"
2735 "#ifdef USELIGHTMAP\n"
2736 "float2 TexCoordLightmap : TEXCOORD1,\n"
2737 "#endif\n"
2738 "#ifdef USEEYEVECTOR\n"
2739 "float3 EyeVector : TEXCOORD2,\n"
2740 "#endif\n"
2741 "#ifdef USEREFLECTION\n"
2742 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2743 "#endif\n"
2744 "#ifdef USEFOG\n"
2745 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2746 "#endif\n"
2747 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2748 "float3 LightVector : TEXCOORD5,\n"
2749 "#endif\n"
2750 "#ifdef MODE_LIGHTSOURCE\n"
2751 "float3 CubeVector : TEXCOORD3,\n"
2752 "#endif\n"
2753 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2754 "float4 ModelViewPosition : TEXCOORD0,\n"
2755 "#endif\n"
2756 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
2757 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2758 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2759 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2760 "#endif\n"
2761 "\n"
2762 "uniform sampler2D Texture_Normal,\n"
2763 "uniform sampler2D Texture_Color,\n"
2764 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2765 "uniform sampler2D Texture_Gloss,\n"
2766 "#endif\n"
2767 "#ifdef USEGLOW\n"
2768 "uniform sampler2D Texture_Glow,\n"
2769 "#endif\n"
2770 "#ifdef USEVERTEXTEXTUREBLEND\n"
2771 "uniform sampler2D Texture_SecondaryNormal,\n"
2772 "uniform sampler2D Texture_SecondaryColor,\n"
2773 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2774 "uniform sampler2D Texture_SecondaryGloss,\n"
2775 "#endif\n"
2776 "#ifdef USEGLOW\n"
2777 "uniform sampler2D Texture_SecondaryGlow,\n"
2778 "#endif\n"
2779 "#endif\n"
2780 "#ifdef USECOLORMAPPING\n"
2781 "uniform sampler2D Texture_Pants,\n"
2782 "uniform sampler2D Texture_Shirt,\n"
2783 "#endif\n"
2784 "#ifdef USEFOG\n"
2785 "uniform sampler2D Texture_FogMask,\n"
2786 "#endif\n"
2787 "#ifdef USELIGHTMAP\n"
2788 "uniform sampler2D Texture_Lightmap,\n"
2789 "#endif\n"
2790 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2791 "uniform sampler2D Texture_Deluxemap,\n"
2792 "#endif\n"
2793 "#ifdef USEREFLECTION\n"
2794 "uniform sampler2D Texture_Reflection,\n"
2795 "#endif\n"
2796 "\n"
2797 "//#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2798 "uniform samplerRECT Texture_ScreenDepth,\n"
2799 "uniform samplerRECT Texture_ScreenNormalMap,\n"
2800 "//#endif\n"
2801 "#ifdef USEDEFERREDLIGHTMAP\n"
2802 "uniform samplerRECT Texture_ScreenDiffuse,\n"
2803 "uniform samplerRECT Texture_ScreenSpecular,\n"
2804 "#endif\n"
2805 "\n"
2806 "#ifdef USECOLORMAPPING\n"
2807 "uniform half3 Color_Pants,\n"
2808 "uniform half3 Color_Shirt,\n"
2809 "#endif\n"
2810 "#ifdef USEFOG\n"
2811 "uniform float3 FogColor,\n"
2812 "uniform float FogRangeRecip,\n"
2813 "uniform float FogPlaneViewDist,\n"
2814 "uniform float FogHeightFade,\n"
2815 "#endif\n"
2816 "\n"
2817 "#ifdef USEOFFSETMAPPING\n"
2818 "uniform float OffsetMapping_Scale,\n"
2819 "#endif\n"
2820 "\n"
2821 "#ifdef USEDEFERREDLIGHTMAP\n"
2822 "uniform half3 DeferredMod_Diffuse,\n"
2823 "uniform half3 DeferredMod_Specular,\n"
2824 "#endif\n"
2825 "uniform half3 Color_Ambient,\n"
2826 "uniform half3 Color_Diffuse,\n"
2827 "uniform half3 Color_Specular,\n"
2828 "uniform half SpecularPower,\n"
2829 "#ifdef USEGLOW\n"
2830 "uniform half3 Color_Glow,\n"
2831 "#endif\n"
2832 "uniform half Alpha,\n"
2833 "#ifdef USEREFLECTION\n"
2834 "uniform float4 DistortScaleRefractReflect,\n"
2835 "uniform float4 ScreenScaleRefractReflect,\n"
2836 "uniform float4 ScreenCenterRefractReflect,\n"
2837 "uniform half4 ReflectColor,\n"
2838 "#endif\n"
2839 "#ifdef MODE_LIGHTDIRECTION\n"
2840 "uniform half3 LightColor,\n"
2841 "#endif\n"
2842 "#ifdef MODE_LIGHTSOURCE\n"
2843 "uniform half3 LightColor,\n"
2844 "#endif\n"
2845 "\n"
2846 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2847 "uniform sampler2D Texture_Attenuation,\n"
2848 "uniform samplerCUBE Texture_Cube,\n"
2849 "\n"
2850 "#ifdef USESHADOWMAPRECT\n"
2851 "# ifdef USESHADOWSAMPLER\n"
2852 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2853 "# else\n"
2854 "uniform samplerRECT Texture_ShadowMapRect,\n"
2855 "# endif\n"
2856 "#endif\n"
2857 "\n"
2858 "#ifdef USESHADOWMAP2D\n"
2859 "# ifdef USESHADOWSAMPLER\n"
2860 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2861 "# else\n"
2862 "uniform sampler2D Texture_ShadowMap2D,\n"
2863 "# endif\n"
2864 "#endif\n"
2865 "\n"
2866 "#ifdef USESHADOWMAPVSDCT\n"
2867 "uniform samplerCUBE Texture_CubeProjection,\n"
2868 "#endif\n"
2869 "\n"
2870 "#ifdef USESHADOWMAPCUBE\n"
2871 "# ifdef USESHADOWSAMPLER\n"
2872 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2873 "# else\n"
2874 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2875 "# endif\n"
2876 "#endif\n"
2877 "\n"
2878 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2879 "uniform float2 ShadowMap_TextureScale,\n"
2880 "uniform float4 ShadowMap_Parameters,\n"
2881 "#endif\n"
2882 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2883 "\n"
2884 "out float4 gl_FragColor : COLOR\n"
2885 ")\n"
2886 "{\n"
2887 "       float2 TexCoord = TexCoordBoth.xy;\n"
2888 "#ifdef USEVERTEXTEXTUREBLEND\n"
2889 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
2890 "#endif\n"
2891 "#ifdef USEOFFSETMAPPING\n"
2892 "       // apply offsetmapping\n"
2893 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2894 "#define TexCoord TexCoordOffset\n"
2895 "#endif\n"
2896 "\n"
2897 "       // combine the diffuse textures (base, pants, shirt)\n"
2898 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
2899 "#ifdef USEALPHAKILL\n"
2900 "       if (color.a < 0.5)\n"
2901 "               discard;\n"
2902 "#endif\n"
2903 "       color.a *= Alpha;\n"
2904 "#ifdef USECOLORMAPPING\n"
2905 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord)) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
2906 "#endif\n"
2907 "#ifdef USEVERTEXTEXTUREBLEND\n"
2908 "       float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
2909 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
2910 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
2911 "       color.rgb = half3(mix(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
2912 "       color.a = 1.0;\n"
2913 "       //color = mix(half4(1, 0, 0, 1), color, terrainblend);\n"
2914 "#endif\n"
2915 "\n"
2916 "       // get the surface normal\n"
2917 "#ifdef USEVERTEXTEXTUREBLEND\n"
2918 "       half3 surfacenormal = normalize(half3(mix(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
2919 "#else\n"
2920 "       half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
2921 "#endif\n"
2922 "\n"
2923 "       // get the material colors\n"
2924 "       half3 diffusetex = color.rgb;\n"
2925 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2926 "# ifdef USEVERTEXTEXTUREBLEND\n"
2927 "       half3 glosstex = half3(mix(float3(tex2D(Texture_SecondaryGloss, TexCoord2)), float3(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
2928 "# else\n"
2929 "       half3 glosstex = half3(tex2D(Texture_Gloss, TexCoord));\n"
2930 "# endif\n"
2931 "#endif\n"
2932 "\n"
2933 "\n"
2934 "\n"
2935 "\n"
2936 "#ifdef MODE_LIGHTSOURCE\n"
2937 "       // light source\n"
2938 "       half3 lightnormal = half3(normalize(LightVector));\n"
2939 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2940 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
2941 "#ifdef USESPECULAR\n"
2942 "#ifdef USEEXACTSPECULARMATH\n"
2943 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
2944 "#else\n"
2945 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
2946 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
2947 "#endif\n"
2948 "       color.rgb += glosstex * (specular * Color_Specular);\n"
2949 "#endif\n"
2950 "       color.rgb *= LightColor;\n"
2951 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2952 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
2953 "       color.rgb *= ShadowMapCompare(CubeVector,\n"
2954 "# if defined(USESHADOWMAP2D)\n"
2955 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2956 "# endif\n"
2957 "# if defined(USESHADOWMAPRECT)\n"
2958 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2959 "# endif\n"
2960 "# if defined(USESHADOWMAPCUBE)\n"
2961 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2962 "# endif\n"
2963 "\n"
2964 "#ifdef USESHADOWMAPVSDCT\n"
2965 ", Texture_CubeProjection\n"
2966 "#endif\n"
2967 "       );\n"
2968 "\n"
2969 "#endif\n"
2970 "# ifdef USECUBEFILTER\n"
2971 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector));\n"
2972 "# endif\n"
2973 "#endif // MODE_LIGHTSOURCE\n"
2974 "\n"
2975 "\n"
2976 "\n"
2977 "\n"
2978 "#ifdef MODE_LIGHTDIRECTION\n"
2979 "#define SHADING\n"
2980 "       half3 lightnormal = half3(normalize(LightVector));\n"
2981 "#define lightcolor LightColor\n"
2982 "#endif // MODE_LIGHTDIRECTION\n"
2983 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2984 "#define SHADING\n"
2985 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
2986 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
2987 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
2988 "       // convert modelspace light vector to tangentspace\n"
2989 "       half3 lightnormal;\n"
2990 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
2991 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
2992 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
2993 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
2994 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
2995 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
2996 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
2997 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
2998 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
2999 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3000 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3001 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3002 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3003 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3004 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3005 "#define SHADING\n"
3006 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3007 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3008 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3009 "#endif\n"
3010 "\n"
3011 "\n"
3012 "\n"
3013 "\n"
3014 "#ifdef MODE_LIGHTMAP\n"
3015 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
3016 "#endif // MODE_LIGHTMAP\n"
3017 "#ifdef MODE_VERTEXCOLOR\n"
3018 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3019 "#endif // MODE_VERTEXCOLOR\n"
3020 "#ifdef MODE_FLATCOLOR\n"
3021 "       color.rgb = diffusetex * Color_Ambient;\n"
3022 "#endif // MODE_FLATCOLOR\n"
3023 "\n"
3024 "\n"
3025 "\n"
3026 "\n"
3027 "#ifdef SHADING\n"
3028 "# ifdef USEDIFFUSE\n"
3029 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3030 "#  ifdef USESPECULAR\n"
3031 "#   ifdef USEEXACTSPECULARMATH\n"
3032 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
3033 "#   else\n"
3034 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3035 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
3036 "#   endif\n"
3037 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
3038 "#  else\n"
3039 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3040 "#  endif\n"
3041 "# else\n"
3042 "       color.rgb = diffusetex * Color_Ambient;\n"
3043 "# endif\n"
3044 "#endif\n"
3045 "\n"
3046 "#ifdef USEDEFERREDLIGHTMAP\n"
3047 "       color.rgb += diffusetex * half3(texRECT(Texture_ScreenDiffuse, Pixel)) * DeferredMod_Diffuse;\n"
3048 "       color.rgb += glosstex * half3(texRECT(Texture_ScreenSpecular, Pixel)) * DeferredMod_Specular;\n"
3049 "       color.rgb = half3(texRECT(Texture_ScreenDepth, Pixel));\n"
3050 "#endif\n"
3051 "\n"
3052 "#ifdef USEGLOW\n"
3053 "#ifdef USEVERTEXTEXTUREBLEND\n"
3054 "       color.rgb += mix(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
3055 "#else\n"
3056 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
3057 "#endif\n"
3058 "#endif\n"
3059 "\n"
3060 "#ifdef USEFOG\n"
3061 "#ifdef MODE_LIGHTSOURCE\n"
3062 "       color.rgb *= half(FogVertex());\n"
3063 "#else\n"
3064 "       color.rgb = mix(FogColor, float3(color.rgb), FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3065 "#endif\n"
3066 "#endif\n"
3067 "\n"
3068 "       // 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"
3069 "#ifdef USEREFLECTION\n"
3070 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3071 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3072 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3073 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
3074 "       // FIXME temporary hack to detect the case that the reflection\n"
3075 "       // gets blackened at edges due to leaving the area that contains actual\n"
3076 "       // content.\n"
3077 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3078 "       // 'appening.\n"
3079 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3080 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3081 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3082 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3083 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3084 "       color.rgb = mix(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
3085 "#endif\n"
3086 "\n"
3087 "       gl_FragColor = float4(color);\n"
3088 "}\n"
3089 "#endif // FRAGMENT_SHADER\n"
3090 "\n"
3091 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3092 "#endif // !MODE_DEFERREDGEOMETRY\n"
3093 "#endif // !MODE_WATER\n"
3094 "#endif // !MODE_REFRACTION\n"
3095 "#endif // !MODE_BLOOMBLUR\n"
3096 "#endif // !MODE_GENERIC\n"
3097 "#endif // !MODE_POSTPROCESS\n"
3098 "#endif // !MODE_SHOWDEPTH\n"
3099 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3100 ;
3101
3102 //=======================================================================================================================================================
3103
3104 typedef struct shaderpermutationinfo_s
3105 {
3106         const char *pretext;
3107         const char *name;
3108 }
3109 shaderpermutationinfo_t;
3110
3111 typedef struct shadermodeinfo_s
3112 {
3113         const char *vertexfilename;
3114         const char *geometryfilename;
3115         const char *fragmentfilename;
3116         const char *pretext;
3117         const char *name;
3118 }
3119 shadermodeinfo_t;
3120
3121 typedef enum shaderpermutation_e
3122 {
3123         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3124         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3125         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3126         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3127         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3128         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3129         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3130         SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
3131         SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
3132         SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
3133         SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
3134         SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
3135         SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
3136         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3137         SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3138         SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3139         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3140         SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
3141         SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
3142         SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
3143         SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
3144         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3145         SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
3146         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3147         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3148         SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3149         SHADERPERMUTATION_LIMIT = 1<<26, ///< size of permutations array
3150         SHADERPERMUTATION_COUNT = 26 ///< size of shaderpermutationinfo array
3151 }
3152 shaderpermutation_t;
3153
3154 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3155 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3156 {
3157         {"#define USEDIFFUSE\n", " diffuse"},
3158         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3159         {"#define USEVIEWTINT\n", " viewtint"},
3160         {"#define USECOLORMAPPING\n", " colormapping"},
3161         {"#define USESATURATION\n", " saturation"},
3162         {"#define USEFOGINSIDE\n", " foginside"},
3163         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3164         {"#define USEGAMMARAMPS\n", " gammaramps"},
3165         {"#define USECUBEFILTER\n", " cubefilter"},
3166         {"#define USEGLOW\n", " glow"},
3167         {"#define USEBLOOM\n", " bloom"},
3168         {"#define USESPECULAR\n", " specular"},
3169         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3170         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3171         {"#define USEREFLECTION\n", " reflection"},
3172         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3173         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3174         {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3175         {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3176         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3177         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3178         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3179         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3180         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3181         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3182         {"#define USEALPHAKILL\n", " alphakill"},
3183 };
3184
3185 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3186 typedef enum shadermode_e
3187 {
3188         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3189         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3190         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3191         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3192         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3193         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3194         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3195         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3196         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3197         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3198         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3199         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3200         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3201         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3202         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3203         SHADERMODE_COUNT
3204 }
3205 shadermode_t;
3206
3207 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3208 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3209 {
3210         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3211         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3212         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3213         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3214         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3215         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3216         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3217         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3218         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3219         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3220         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3221         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3222         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3223         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3224         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3225 };
3226
3227 #ifdef SUPPORTCG
3228 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3229 {
3230         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3231         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3232         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3233         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3234         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3235         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3236         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3237         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3238         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3239         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3240         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3241         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3242         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3243         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3244         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3245 };
3246 #endif
3247
3248 struct r_glsl_permutation_s;
3249 typedef struct r_glsl_permutation_s
3250 {
3251         /// hash lookup data
3252         struct r_glsl_permutation_s *hashnext;
3253         unsigned int mode;
3254         unsigned int permutation;
3255
3256         /// indicates if we have tried compiling this permutation already
3257         qboolean compiled;
3258         /// 0 if compilation failed
3259         int program;
3260         /// locations of detected uniforms in program object, or -1 if not found
3261         int loc_Texture_First;
3262         int loc_Texture_Second;
3263         int loc_Texture_GammaRamps;
3264         int loc_Texture_Normal;
3265         int loc_Texture_Color;
3266         int loc_Texture_Gloss;
3267         int loc_Texture_Glow;
3268         int loc_Texture_SecondaryNormal;
3269         int loc_Texture_SecondaryColor;
3270         int loc_Texture_SecondaryGloss;
3271         int loc_Texture_SecondaryGlow;
3272         int loc_Texture_Pants;
3273         int loc_Texture_Shirt;
3274         int loc_Texture_FogMask;
3275         int loc_Texture_Lightmap;
3276         int loc_Texture_Deluxemap;
3277         int loc_Texture_Attenuation;
3278         int loc_Texture_Cube;
3279         int loc_Texture_Refraction;
3280         int loc_Texture_Reflection;
3281         int loc_Texture_ShadowMapRect;
3282         int loc_Texture_ShadowMapCube;
3283         int loc_Texture_ShadowMap2D;
3284         int loc_Texture_CubeProjection;
3285         int loc_Texture_ScreenDepth;
3286         int loc_Texture_ScreenNormalMap;
3287         int loc_Texture_ScreenDiffuse;
3288         int loc_Texture_ScreenSpecular;
3289         int loc_Alpha;
3290         int loc_BloomBlur_Parameters;
3291         int loc_ClientTime;
3292         int loc_Color_Ambient;
3293         int loc_Color_Diffuse;
3294         int loc_Color_Specular;
3295         int loc_Color_Glow;
3296         int loc_Color_Pants;
3297         int loc_Color_Shirt;
3298         int loc_DeferredColor_Ambient;
3299         int loc_DeferredColor_Diffuse;
3300         int loc_DeferredColor_Specular;
3301         int loc_DeferredMod_Diffuse;
3302         int loc_DeferredMod_Specular;
3303         int loc_DistortScaleRefractReflect;
3304         int loc_EyePosition;
3305         int loc_FogColor;
3306         int loc_FogHeightFade;
3307         int loc_FogPlane;
3308         int loc_FogPlaneViewDist;
3309         int loc_FogRangeRecip;
3310         int loc_LightColor;
3311         int loc_LightDir;
3312         int loc_LightPosition;
3313         int loc_OffsetMapping_Scale;
3314         int loc_PixelSize;
3315         int loc_ReflectColor;
3316         int loc_ReflectFactor;
3317         int loc_ReflectOffset;
3318         int loc_RefractColor;
3319         int loc_Saturation;
3320         int loc_ScreenCenterRefractReflect;
3321         int loc_ScreenScaleRefractReflect;
3322         int loc_ScreenToDepth;
3323         int loc_ShadowMap_Parameters;
3324         int loc_ShadowMap_TextureScale;
3325         int loc_SpecularPower;
3326         int loc_UserVec1;
3327         int loc_UserVec2;
3328         int loc_UserVec3;
3329         int loc_UserVec4;
3330         int loc_ViewTintColor;
3331         int loc_ViewToLight;
3332         int loc_ModelToLight;
3333         int loc_TexMatrix;
3334         int loc_BackgroundTexMatrix;
3335         int loc_ModelViewProjectionMatrix;
3336         int loc_ModelViewMatrix;
3337 }
3338 r_glsl_permutation_t;
3339
3340 #define SHADERPERMUTATION_HASHSIZE 256
3341
3342 /// information about each possible shader permutation
3343 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3344 /// currently selected permutation
3345 r_glsl_permutation_t *r_glsl_permutation;
3346 /// storage for permutations linked in the hash table
3347 memexpandablearray_t r_glsl_permutationarray;
3348
3349 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3350 {
3351         //unsigned int hashdepth = 0;
3352         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3353         r_glsl_permutation_t *p;
3354         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3355         {
3356                 if (p->mode == mode && p->permutation == permutation)
3357                 {
3358                         //if (hashdepth > 10)
3359                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3360                         return p;
3361                 }
3362                 //hashdepth++;
3363         }
3364         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3365         p->mode = mode;
3366         p->permutation = permutation;
3367         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3368         r_glsl_permutationhash[mode][hashindex] = p;
3369         //if (hashdepth > 10)
3370         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3371         return p;
3372 }
3373
3374 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3375 {
3376         char *shaderstring;
3377         if (!filename || !filename[0])
3378                 return NULL;
3379         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3380         if (shaderstring)
3381         {
3382                 if (printfromdisknotice)
3383                         Con_DPrintf("from disk %s... ", filename);
3384                 return shaderstring;
3385         }
3386         else if (!strcmp(filename, "glsl/default.glsl"))
3387         {
3388                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
3389                 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
3390         }
3391         return shaderstring;
3392 }
3393
3394 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3395 {
3396         int i;
3397         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3398         int vertstrings_count = 0;
3399         int geomstrings_count = 0;
3400         int fragstrings_count = 0;
3401         char *vertexstring, *geometrystring, *fragmentstring;
3402         const char *vertstrings_list[32+3];
3403         const char *geomstrings_list[32+3];
3404         const char *fragstrings_list[32+3];
3405         char permutationname[256];
3406
3407         if (p->compiled)
3408                 return;
3409         p->compiled = true;
3410         p->program = 0;
3411
3412         permutationname[0] = 0;
3413         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3414         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3415         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3416
3417         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3418
3419         // the first pretext is which type of shader to compile as
3420         // (later these will all be bound together as a program object)
3421         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3422         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3423         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3424
3425         // the second pretext is the mode (for example a light source)
3426         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3427         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3428         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3429         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3430
3431         // now add all the permutation pretexts
3432         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3433         {
3434                 if (permutation & (1<<i))
3435                 {
3436                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3437                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3438                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3439                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3440                 }
3441                 else
3442                 {
3443                         // keep line numbers correct
3444                         vertstrings_list[vertstrings_count++] = "\n";
3445                         geomstrings_list[geomstrings_count++] = "\n";
3446                         fragstrings_list[fragstrings_count++] = "\n";
3447                 }
3448         }
3449
3450         // now append the shader text itself
3451         vertstrings_list[vertstrings_count++] = vertexstring;
3452         geomstrings_list[geomstrings_count++] = geometrystring;
3453         fragstrings_list[fragstrings_count++] = fragmentstring;
3454
3455         // if any sources were NULL, clear the respective list
3456         if (!vertexstring)
3457                 vertstrings_count = 0;
3458         if (!geometrystring)
3459                 geomstrings_count = 0;
3460         if (!fragmentstring)
3461                 fragstrings_count = 0;
3462
3463         // compile the shader program
3464         if (vertstrings_count + geomstrings_count + fragstrings_count)
3465                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3466         if (p->program)
3467         {
3468                 CHECKGLERROR
3469                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3470                 // look up all the uniform variable names we care about, so we don't
3471                 // have to look them up every time we set them
3472
3473                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3474                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3475                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3476                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3477                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3478                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3479                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3480                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3481                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3482                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3483                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3484                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3485                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3486                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3487                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3488                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3489                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3490                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3491                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3492                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3493                 p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3494                 p->loc_Texture_ShadowMapCube      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3495                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3496                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3497                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3498                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3499                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3500                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3501                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3502                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3503                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3504                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3505                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3506                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3507                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3508                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3509                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3510                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3511                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3512                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3513                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3514                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3515                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3516                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3517                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3518                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3519                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3520                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3521                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3522                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3523                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3524                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3525                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3526                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3527                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3528                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3529                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3530                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3531                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3532                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3533                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3534                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3535                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3536                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3537                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3538                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3539                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3540                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3541                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3542                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3543                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3544                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3545                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3546                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3547                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3548                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3549                 // initialize the samplers to refer to the texture units we use
3550                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3551                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3552                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3553                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3554                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3555                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3556                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3557                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3558                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3559                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3560                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3561                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3562                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3563                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3564                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3565                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3566                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3567                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3568                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3569                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3570                 if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , GL20TU_SHADOWMAPRECT);
3571                 if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
3572                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
3573                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3574                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3575                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3576                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3577                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3578                 CHECKGLERROR
3579                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3580         }
3581         else
3582                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3583
3584         // free the strings
3585         if (vertexstring)
3586                 Mem_Free(vertexstring);
3587         if (geometrystring)
3588                 Mem_Free(geometrystring);
3589         if (fragmentstring)
3590                 Mem_Free(fragmentstring);
3591 }
3592
3593 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3594 {
3595         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3596         if (r_glsl_permutation != perm)
3597         {
3598                 r_glsl_permutation = perm;
3599                 if (!r_glsl_permutation->program)
3600                 {
3601                         if (!r_glsl_permutation->compiled)
3602                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3603                         if (!r_glsl_permutation->program)
3604                         {
3605                                 // remove features until we find a valid permutation
3606                                 int i;
3607                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3608                                 {
3609                                         // reduce i more quickly whenever it would not remove any bits
3610                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3611                                         if (!(permutation & j))
3612                                                 continue;
3613                                         permutation -= j;
3614                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3615                                         if (!r_glsl_permutation->compiled)
3616                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3617                                         if (r_glsl_permutation->program)
3618                                                 break;
3619                                 }
3620                                 if (i >= SHADERPERMUTATION_COUNT)
3621                                 {
3622                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3623                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3624                                         qglUseProgramObjectARB(0);CHECKGLERROR
3625                                         return; // no bit left to clear, entire mode is broken
3626                                 }
3627                         }
3628                 }
3629                 CHECKGLERROR
3630                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3631         }
3632         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3633         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3634 }
3635
3636 #ifdef SUPPORTCG
3637 #include <Cg/cgGL.h>
3638 struct r_cg_permutation_s;
3639 typedef struct r_cg_permutation_s
3640 {
3641         /// hash lookup data
3642         struct r_cg_permutation_s *hashnext;
3643         unsigned int mode;
3644         unsigned int permutation;
3645
3646         /// indicates if we have tried compiling this permutation already
3647         qboolean compiled;
3648         /// 0 if compilation failed
3649         CGprogram vprogram;
3650         CGprogram fprogram;
3651         /// locations of detected parameters in programs, or NULL if not found
3652         CGparameter vp_EyePosition;
3653         CGparameter vp_FogPlane;
3654         CGparameter vp_LightDir;
3655         CGparameter vp_LightPosition;
3656         CGparameter vp_ModelToLight;
3657         CGparameter vp_TexMatrix;
3658         CGparameter vp_BackgroundTexMatrix;
3659         CGparameter vp_ModelViewProjectionMatrix;
3660         CGparameter vp_ModelViewMatrix;
3661
3662         CGparameter fp_Texture_First;
3663         CGparameter fp_Texture_Second;
3664         CGparameter fp_Texture_GammaRamps;
3665         CGparameter fp_Texture_Normal;
3666         CGparameter fp_Texture_Color;
3667         CGparameter fp_Texture_Gloss;
3668         CGparameter fp_Texture_Glow;
3669         CGparameter fp_Texture_SecondaryNormal;
3670         CGparameter fp_Texture_SecondaryColor;
3671         CGparameter fp_Texture_SecondaryGloss;
3672         CGparameter fp_Texture_SecondaryGlow;
3673         CGparameter fp_Texture_Pants;
3674         CGparameter fp_Texture_Shirt;
3675         CGparameter fp_Texture_FogMask;
3676         CGparameter fp_Texture_Lightmap;
3677         CGparameter fp_Texture_Deluxemap;
3678         CGparameter fp_Texture_Attenuation;
3679         CGparameter fp_Texture_Cube;
3680         CGparameter fp_Texture_Refraction;
3681         CGparameter fp_Texture_Reflection;
3682         CGparameter fp_Texture_ShadowMapRect;
3683         CGparameter fp_Texture_ShadowMapCube;
3684         CGparameter fp_Texture_ShadowMap2D;
3685         CGparameter fp_Texture_CubeProjection;
3686         CGparameter fp_Texture_ScreenDepth;
3687         CGparameter fp_Texture_ScreenNormalMap;
3688         CGparameter fp_Texture_ScreenDiffuse;
3689         CGparameter fp_Texture_ScreenSpecular;
3690         CGparameter fp_Alpha;
3691         CGparameter fp_BloomBlur_Parameters;
3692         CGparameter fp_ClientTime;
3693         CGparameter fp_Color_Ambient;
3694         CGparameter fp_Color_Diffuse;
3695         CGparameter fp_Color_Specular;
3696         CGparameter fp_Color_Glow;
3697         CGparameter fp_Color_Pants;
3698         CGparameter fp_Color_Shirt;
3699         CGparameter fp_DeferredColor_Ambient;
3700         CGparameter fp_DeferredColor_Diffuse;
3701         CGparameter fp_DeferredColor_Specular;
3702         CGparameter fp_DeferredMod_Diffuse;
3703         CGparameter fp_DeferredMod_Specular;
3704         CGparameter fp_DistortScaleRefractReflect;
3705         CGparameter fp_EyePosition;
3706         CGparameter fp_FogColor;
3707         CGparameter fp_FogHeightFade;
3708         CGparameter fp_FogPlane;
3709         CGparameter fp_FogPlaneViewDist;
3710         CGparameter fp_FogRangeRecip;
3711         CGparameter fp_LightColor;
3712         CGparameter fp_LightDir;
3713         CGparameter fp_LightPosition;
3714         CGparameter fp_OffsetMapping_Scale;
3715         CGparameter fp_PixelSize;
3716         CGparameter fp_ReflectColor;
3717         CGparameter fp_ReflectFactor;
3718         CGparameter fp_ReflectOffset;
3719         CGparameter fp_RefractColor;
3720         CGparameter fp_Saturation;
3721         CGparameter fp_ScreenCenterRefractReflect;
3722         CGparameter fp_ScreenScaleRefractReflect;
3723         CGparameter fp_ScreenToDepth;
3724         CGparameter fp_ShadowMap_Parameters;
3725         CGparameter fp_ShadowMap_TextureScale;
3726         CGparameter fp_SpecularPower;
3727         CGparameter fp_UserVec1;
3728         CGparameter fp_UserVec2;
3729         CGparameter fp_UserVec3;
3730         CGparameter fp_UserVec4;
3731         CGparameter fp_ViewTintColor;
3732         CGparameter fp_ViewToLight;
3733 }
3734 r_cg_permutation_t;
3735
3736 /// information about each possible shader permutation
3737 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3738 /// currently selected permutation
3739 r_cg_permutation_t *r_cg_permutation;
3740 /// storage for permutations linked in the hash table
3741 memexpandablearray_t r_cg_permutationarray;
3742
3743 #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));}}
3744
3745 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3746 {
3747         //unsigned int hashdepth = 0;
3748         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3749         r_cg_permutation_t *p;
3750         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3751         {
3752                 if (p->mode == mode && p->permutation == permutation)
3753                 {
3754                         //if (hashdepth > 10)
3755                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3756                         return p;
3757                 }
3758                 //hashdepth++;
3759         }
3760         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3761         p->mode = mode;
3762         p->permutation = permutation;
3763         p->hashnext = r_cg_permutationhash[mode][hashindex];
3764         r_cg_permutationhash[mode][hashindex] = p;
3765         //if (hashdepth > 10)
3766         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3767         return p;
3768 }
3769
3770 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3771 {
3772         char *shaderstring;
3773         if (!filename || !filename[0])
3774                 return NULL;
3775         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3776         if (shaderstring)
3777         {
3778                 if (printfromdisknotice)
3779                         Con_DPrintf("from disk %s... ", filename);
3780                 return shaderstring;
3781         }
3782         else if (!strcmp(filename, "cg/default.cg"))
3783         {
3784                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtincgshaderstring) + 1);
3785                 memcpy(shaderstring, builtincgshaderstring, strlen(builtincgshaderstring) + 1);
3786         }
3787         return shaderstring;
3788 }
3789
3790 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
3791 {
3792         int i;
3793         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
3794         int vertstrings_count = 0, vertstring_length = 0;
3795         int geomstrings_count = 0, geomstring_length = 0;
3796         int fragstrings_count = 0, fragstring_length = 0;
3797         char *t;
3798         char *vertexstring, *geometrystring, *fragmentstring;
3799         char *vertstring, *geomstring, *fragstring;
3800         const char *vertstrings_list[32+3];
3801         const char *geomstrings_list[32+3];
3802         const char *fragstrings_list[32+3];
3803         char permutationname[256];
3804         CGprofile vertexProfile;
3805         CGprofile fragmentProfile;
3806
3807         if (p->compiled)
3808                 return;
3809         p->compiled = true;
3810         p->vprogram = NULL;
3811         p->fprogram = NULL;
3812
3813         permutationname[0] = 0;
3814         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
3815         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
3816         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
3817
3818         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3819
3820         // the first pretext is which type of shader to compile as
3821         // (later these will all be bound together as a program object)
3822         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3823         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3824         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3825
3826         // the second pretext is the mode (for example a light source)
3827         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3828         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3829         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3830         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3831
3832         // now add all the permutation pretexts
3833         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3834         {
3835                 if (permutation & (1<<i))
3836                 {
3837                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3838                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3839                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3840                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3841                 }
3842                 else
3843                 {
3844                         // keep line numbers correct
3845                         vertstrings_list[vertstrings_count++] = "\n";
3846                         geomstrings_list[geomstrings_count++] = "\n";
3847                         fragstrings_list[fragstrings_count++] = "\n";
3848                 }
3849         }
3850
3851         // now append the shader text itself
3852         vertstrings_list[vertstrings_count++] = vertexstring;
3853         geomstrings_list[geomstrings_count++] = geometrystring;
3854         fragstrings_list[fragstrings_count++] = fragmentstring;
3855
3856         // if any sources were NULL, clear the respective list
3857         if (!vertexstring)
3858                 vertstrings_count = 0;
3859         if (!geometrystring)
3860                 geomstrings_count = 0;
3861         if (!fragmentstring)
3862                 fragstrings_count = 0;
3863
3864         vertstring_length = 0;
3865         for (i = 0;i < vertstrings_count;i++)
3866                 vertstring_length += strlen(vertstrings_list[i]);
3867         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
3868         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
3869                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
3870
3871         geomstring_length = 0;
3872         for (i = 0;i < geomstrings_count;i++)
3873                 geomstring_length += strlen(geomstrings_list[i]);
3874         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
3875         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
3876                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
3877
3878         fragstring_length = 0;
3879         for (i = 0;i < fragstrings_count;i++)
3880                 fragstring_length += strlen(fragstrings_list[i]);
3881         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
3882         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
3883                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
3884
3885         CHECKGLERROR
3886         CHECKCGERROR
3887         //vertexProfile = CG_PROFILE_ARBVP1;
3888         //fragmentProfile = CG_PROFILE_ARBFP1;
3889         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
3890         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
3891         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
3892         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
3893         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
3894         CHECKGLERROR
3895
3896         // compile the vertex program
3897         if (vertstring[0] && (p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, CG_PROFILE_ARBVP1, NULL, NULL)))
3898         {
3899                 CHECKCGERROR
3900                 cgCompileProgram(p->vprogram);CHECKCGERROR
3901                 if (!cgIsProgramCompiled(p->vprogram))
3902                 {
3903                         CHECKCGERROR
3904                         cgDestroyProgram(p->vprogram);CHECKCGERROR
3905                         p->vprogram = 0;
3906                 }
3907                 else
3908                 {
3909                         cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
3910                         cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
3911                         // look up all the uniform variable names we care about, so we don't
3912                         // have to look them up every time we set them
3913                         CHECKCGERROR
3914                         p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
3915                         p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
3916                         p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
3917                         p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
3918                         p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
3919                         p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
3920                         p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
3921                         p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
3922                         p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
3923                         CHECKCGERROR
3924                 }
3925         }
3926
3927         // compile the fragment program
3928         if (fragstring[0] && (p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, CG_PROFILE_ARBFP1, NULL, NULL)))
3929         {
3930                 cgCompileProgram(p->fprogram);CHECKCGERROR
3931                 if (!cgIsProgramCompiled(p->fprogram))
3932                 {
3933                         CHECKCGERROR
3934                         cgDestroyProgram(p->fprogram);CHECKCGERROR
3935                         p->fprogram = 0;
3936                 }
3937                 else
3938                 {
3939                         cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
3940                         cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
3941                         CHECKCGERROR
3942                         p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
3943                         p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
3944                         p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
3945                         p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
3946                         p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
3947                         p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
3948                         p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
3949                         p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
3950                         p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
3951                         p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
3952                         p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
3953                         p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
3954                         p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
3955                         p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
3956                         p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
3957                         p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
3958                         p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
3959                         p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
3960                         p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
3961                         p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
3962                         p->fp_Texture_ShadowMapRect      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
3963                         p->fp_Texture_ShadowMapCube      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
3964                         p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
3965                         p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
3966                         p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
3967                         p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
3968                         p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
3969                         p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
3970                         p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
3971                         p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
3972                         p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
3973                         p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
3974                         p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
3975                         p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
3976                         p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
3977                         p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
3978                         p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
3979                         p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
3980                         p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
3981                         p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
3982                         p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
3983                         p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
3984                         p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
3985                         p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
3986                         p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
3987                         p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
3988                         p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
3989                         p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
3990                         p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
3991                         p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
3992                         p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
3993                         p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
3994                         p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
3995                         p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
3996                         p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
3997                         p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
3998                         p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
3999                         p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4000                         p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4001                         p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4002                         p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4003                         p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4004                         p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4005                         p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4006                         p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4007                         p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4008                         p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4009                         p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4010                         p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4011                         p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4012                         p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4013                         CHECKCGERROR
4014                 }
4015         }
4016
4017         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4018                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4019         else
4020                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4021
4022         // free the strings
4023         if (vertstring)
4024                 Mem_Free(vertstring);
4025         if (geomstring)
4026                 Mem_Free(geomstring);
4027         if (fragstring)
4028                 Mem_Free(fragstring);
4029         if (vertexstring)
4030                 Mem_Free(vertexstring);
4031         if (geometrystring)
4032                 Mem_Free(geometrystring);
4033         if (fragmentstring)
4034                 Mem_Free(fragmentstring);
4035 }
4036
4037 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4038 {
4039         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4040         CHECKGLERROR
4041         CHECKCGERROR
4042         if (r_cg_permutation != perm)
4043         {
4044                 r_cg_permutation = perm;
4045                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4046                 {
4047                         if (!r_cg_permutation->compiled)
4048                                 R_CG_CompilePermutation(perm, mode, permutation);
4049                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4050                         {
4051                                 // remove features until we find a valid permutation
4052                                 int i;
4053                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4054                                 {
4055                                         // reduce i more quickly whenever it would not remove any bits
4056                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4057                                         if (!(permutation & j))
4058                                                 continue;
4059                                         permutation -= j;
4060                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4061                                         if (!r_cg_permutation->compiled)
4062                                                 R_CG_CompilePermutation(perm, mode, permutation);
4063                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4064                                                 break;
4065                                 }
4066                                 if (i >= SHADERPERMUTATION_COUNT)
4067                                 {
4068                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4069                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4070                                         return; // no bit left to clear, entire mode is broken
4071                                 }
4072                         }
4073                 }
4074                 CHECKGLERROR
4075                 CHECKCGERROR
4076                 if (r_cg_permutation->vprogram)
4077                 {
4078                         //cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4079                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4080                         //cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4081                 }
4082                 else
4083                 {
4084                         //cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4085                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4086                 }
4087                 if (r_cg_permutation->fprogram)
4088                 {
4089                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4090                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4091                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4092                 }
4093                 else
4094                 {
4095                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4096                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4097                 }
4098         }
4099         CHECKCGERROR
4100         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4101         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4102 }
4103
4104 void CG_BindTexture(CGparameter param, int texnum)
4105 {
4106         cgGLSetTextureParameter(param, texnum);
4107         cgGLEnableTextureParameter(param);
4108 }
4109 #endif
4110
4111 void R_GLSL_Restart_f(void)
4112 {
4113         unsigned int i, limit;
4114         switch(vid.renderpath)
4115         {
4116         case RENDERPATH_GL20:
4117                 {
4118                         r_glsl_permutation_t *p;
4119                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4120                         for (i = 0;i < limit;i++)
4121                         {
4122                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4123                                 {
4124                                         GL_Backend_FreeProgram(p->program);
4125                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4126                                 }
4127                         }
4128                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4129                 }
4130                 break;
4131         case RENDERPATH_CGGL:
4132 #ifdef SUPPORTCG
4133                 {
4134                         r_cg_permutation_t *p;
4135                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4136                         for (i = 0;i < limit;i++)
4137                         {
4138                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4139                                 {
4140                                         if (p->vprogram)
4141                                                 cgDestroyProgram(p->vprogram);
4142                                         if (p->fprogram)
4143                                                 cgDestroyProgram(p->fprogram);
4144                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4145                                 }
4146                         }
4147                 }
4148                 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4149                 break;
4150 #endif
4151         case RENDERPATH_GL13:
4152         case RENDERPATH_GL11:
4153                 break;
4154         }
4155 }
4156
4157 void R_GLSL_DumpShader_f(void)
4158 {
4159         int i;
4160         qfile_t *file;
4161
4162         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4163         if (file)
4164         {
4165                 FS_Print(file, "/* The engine may define the following macros:\n");
4166                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4167                 for (i = 0;i < SHADERMODE_COUNT;i++)
4168                         FS_Print(file, glslshadermodeinfo[i].pretext);
4169                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4170                         FS_Print(file, shaderpermutationinfo[i].pretext);
4171                 FS_Print(file, "*/\n");
4172                 FS_Print(file, builtinshaderstring);
4173                 FS_Close(file);
4174                 Con_Printf("glsl/default.glsl written\n");
4175         }
4176         else
4177                 Con_Printf("failed to write to glsl/default.glsl\n");
4178
4179 #ifdef SUPPORTCG
4180         file = FS_OpenRealFile("cg/default.cg", "w", false);
4181         if (file)
4182         {
4183                 FS_Print(file, "/* The engine may define the following macros:\n");
4184                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4185                 for (i = 0;i < SHADERMODE_COUNT;i++)
4186                         FS_Print(file, cgshadermodeinfo[i].pretext);
4187                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4188                         FS_Print(file, shaderpermutationinfo[i].pretext);
4189                 FS_Print(file, "*/\n");
4190                 FS_Print(file, builtincgshaderstring);
4191                 FS_Close(file);
4192                 Con_Printf("cg/default.cg written\n");
4193         }
4194         else
4195                 Con_Printf("failed to write to cg/default.cg\n");
4196 #endif
4197 }
4198
4199 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4200 {
4201         if (!second)
4202                 texturemode = GL_MODULATE;
4203         switch (vid.renderpath)
4204         {
4205         case RENDERPATH_GL20:
4206                 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))));
4207                 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
4208                 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, second);
4209                 break;
4210         case RENDERPATH_CGGL:
4211 #ifdef SUPPORTCG
4212                 CHECKCGERROR
4213                 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))));
4214                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4215                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4216 #endif
4217                 break;
4218         case RENDERPATH_GL13:
4219                 R_Mesh_TexBind(0, first );
4220                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4221                 R_Mesh_TexBind(1, second);
4222                 if (second)
4223                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4224                 break;
4225         case RENDERPATH_GL11:
4226                 R_Mesh_TexBind(0, first );
4227                 break;
4228         }
4229 }
4230
4231 void R_SetupShader_DepthOrShadow(void)
4232 {
4233         switch (vid.renderpath)
4234         {
4235         case RENDERPATH_GL20:
4236                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4237                 break;
4238         case RENDERPATH_CGGL:
4239 #ifdef SUPPORTCG
4240                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4241 #endif
4242                 break;
4243         case RENDERPATH_GL13:
4244                 R_Mesh_TexBind(0, 0);
4245                 R_Mesh_TexBind(1, 0);
4246                 break;
4247         case RENDERPATH_GL11:
4248                 R_Mesh_TexBind(0, 0);
4249                 break;
4250         }
4251 }
4252
4253 void R_SetupShader_ShowDepth(void)
4254 {
4255         switch (vid.renderpath)
4256         {
4257         case RENDERPATH_GL20:
4258                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4259                 break;
4260         case RENDERPATH_CGGL:
4261 #ifdef SUPPORTCG
4262                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4263 #endif
4264                 break;
4265         case RENDERPATH_GL13:
4266                 break;
4267         case RENDERPATH_GL11:
4268                 break;
4269         }
4270 }
4271
4272 extern qboolean r_shadow_usingdeferredprepass;
4273 extern cvar_t r_shadow_deferred_8bitrange;
4274 extern rtexture_t *r_shadow_attenuationgradienttexture;
4275 extern rtexture_t *r_shadow_attenuation2dtexture;
4276 extern rtexture_t *r_shadow_attenuation3dtexture;
4277 extern qboolean r_shadow_usingshadowmaprect;
4278 extern qboolean r_shadow_usingshadowmapcube;
4279 extern qboolean r_shadow_usingshadowmap2d;
4280 extern float r_shadow_shadowmap_texturescale[2];
4281 extern float r_shadow_shadowmap_parameters[4];
4282 extern qboolean r_shadow_shadowmapvsdct;
4283 extern qboolean r_shadow_shadowmapsampler;
4284 extern int r_shadow_shadowmappcf;
4285 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4286 extern rtexture_t *r_shadow_shadowmap2dtexture;
4287 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4288 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4289 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4290 extern int r_shadow_prepass_width;
4291 extern int r_shadow_prepass_height;
4292 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4293 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4294 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4295 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4296 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
4297 {
4298         // select a permutation of the lighting shader appropriate to this
4299         // combination of texture, entity, light source, and fogging, only use the
4300         // minimum features necessary to avoid wasting rendering time in the
4301         // fragment shader on features that are not being used
4302         unsigned int permutation = 0;
4303         unsigned int mode = 0;
4304         float m16f[16];
4305         if (rsurfacepass == RSURFPASS_BACKGROUND)
4306         {
4307                 // distorted background
4308                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4309                         mode = SHADERMODE_WATER;
4310                 else
4311                         mode = SHADERMODE_REFRACTION;
4312                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4313                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4314                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4315                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4316                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4317                 R_Mesh_ColorPointer(NULL, 0, 0);
4318                 GL_AlphaTest(false);
4319                 GL_BlendFunc(GL_ONE, GL_ZERO);
4320         }
4321         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4322         {
4323                 if (r_glsl_offsetmapping.integer)
4324                 {
4325                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4326                         if (r_glsl_offsetmapping_reliefmapping.integer)
4327                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4328                 }
4329                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4330                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4331                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4332                         permutation |= SHADERPERMUTATION_ALPHAKILL;
4333                 // normalmap (deferred prepass), may use alpha test on diffuse
4334                 mode = SHADERMODE_DEFERREDGEOMETRY;
4335                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4336                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4337                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4338                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4339                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4340                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4341                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4342                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4343                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4344                 else
4345                         R_Mesh_ColorPointer(NULL, 0, 0);
4346                 GL_AlphaTest(false);
4347                 GL_BlendFunc(GL_ONE, GL_ZERO);
4348         }
4349         else if (rsurfacepass == RSURFPASS_RTLIGHT)
4350         {
4351                 if (r_glsl_offsetmapping.integer)
4352                 {
4353                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4354                         if (r_glsl_offsetmapping_reliefmapping.integer)
4355                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4356                 }
4357                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4358                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4359                 // light source
4360                 mode = SHADERMODE_LIGHTSOURCE;
4361                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4362                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4363                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4364                         permutation |= SHADERPERMUTATION_CUBEFILTER;
4365                 if (diffusescale > 0)
4366                         permutation |= SHADERPERMUTATION_DIFFUSE;
4367                 if (specularscale > 0)
4368                 {
4369                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4370                         if (r_shadow_glossexact.integer)
4371                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4372                 }
4373                 if (r_refdef.fogenabled)
4374                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4375                 if (rsurface.texture->colormapping)
4376                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4377                 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4378                 {
4379                         if (r_shadow_usingshadowmaprect)
4380                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4381                         if (r_shadow_usingshadowmap2d)
4382                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4383                         if (r_shadow_usingshadowmapcube)
4384                                 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4385                         else if(r_shadow_shadowmapvsdct)
4386                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4387
4388                         if (r_shadow_shadowmapsampler)
4389                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4390                         if (r_shadow_shadowmappcf > 1)
4391                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4392                         else if (r_shadow_shadowmappcf)
4393                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4394                 }
4395                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4396                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4397                 {
4398                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4399                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4400                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4401                 }
4402                 else
4403                 {
4404                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4405                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4406                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4407                 }
4408                 //R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4409                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4410                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4411                 else
4412                         R_Mesh_ColorPointer(NULL, 0, 0);
4413                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4414                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4415         }
4416         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4417         {
4418                 if (r_glsl_offsetmapping.integer)
4419                 {
4420                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4421                         if (r_glsl_offsetmapping_reliefmapping.integer)
4422                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4423                 }
4424                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4425                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4426                 // unshaded geometry (fullbright or ambient model lighting)
4427                 mode = SHADERMODE_FLATCOLOR;
4428                 ambientscale = diffusescale = specularscale = 0;
4429                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4430                         permutation |= SHADERPERMUTATION_GLOW;
4431                 if (r_refdef.fogenabled)
4432                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4433                 if (rsurface.texture->colormapping)
4434                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4435                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4436                         permutation |= SHADERPERMUTATION_REFLECTION;
4437                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4438                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4439                 {
4440                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4441                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4442                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4443                 }
4444                 else
4445                 {
4446                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4447                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4448                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4449                 }
4450                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4451                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4452                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4453                 else
4454                         R_Mesh_ColorPointer(NULL, 0, 0);
4455                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4456                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4457         }
4458         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4459         {
4460                 if (r_glsl_offsetmapping.integer)
4461                 {
4462                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4463                         if (r_glsl_offsetmapping_reliefmapping.integer)
4464                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4465                 }
4466                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4467                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4468                 // directional model lighting
4469                 mode = SHADERMODE_LIGHTDIRECTION;
4470                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4471                         permutation |= SHADERPERMUTATION_GLOW;
4472                 permutation |= SHADERPERMUTATION_DIFFUSE;
4473                 if (specularscale > 0)
4474                 {
4475                         permutation |= SHADERPERMUTATION_SPECULAR;
4476                         if (r_shadow_glossexact.integer)
4477                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4478                 }
4479                 if (r_refdef.fogenabled)
4480                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4481                 if (rsurface.texture->colormapping)
4482                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4483                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4484                         permutation |= SHADERPERMUTATION_REFLECTION;
4485                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4486                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4487                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4488                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4489                 {
4490                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4491                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4492                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4493                 }
4494                 else
4495                 {
4496                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4497                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4498                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4499                 }
4500                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4501                 R_Mesh_ColorPointer(NULL, 0, 0);
4502                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4503                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4504         }
4505         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
4506         {
4507                 if (r_glsl_offsetmapping.integer)
4508                 {
4509                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4510                         if (r_glsl_offsetmapping_reliefmapping.integer)
4511                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4512                 }
4513                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4514                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4515                 // ambient model lighting
4516                 mode = SHADERMODE_LIGHTDIRECTION;
4517                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4518                         permutation |= SHADERPERMUTATION_GLOW;
4519                 if (r_refdef.fogenabled)
4520                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4521                 if (rsurface.texture->colormapping)
4522                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4523                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4524                         permutation |= SHADERPERMUTATION_REFLECTION;
4525                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4526                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4527                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4528                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4529                 {
4530                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4531                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4532                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4533                 }
4534                 else
4535                 {
4536                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4537                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4538                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4539                 }
4540                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4541                 R_Mesh_ColorPointer(NULL, 0, 0);
4542                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4543                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4544         }
4545         else
4546         {
4547                 if (r_glsl_offsetmapping.integer)
4548                 {
4549                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4550                         if (r_glsl_offsetmapping_reliefmapping.integer)
4551                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4552                 }
4553                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4554                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4555                 // lightmapped wall
4556                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4557                         permutation |= SHADERPERMUTATION_GLOW;
4558                 if (r_refdef.fogenabled)
4559                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4560                 if (rsurface.texture->colormapping)
4561                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4562                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4563                         permutation |= SHADERPERMUTATION_REFLECTION;
4564                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4565                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4566                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
4567                 {
4568                         // deluxemapping (light direction texture)
4569                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
4570                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
4571                         else
4572                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4573                         permutation |= SHADERPERMUTATION_DIFFUSE;
4574                         if (specularscale > 0)
4575                         {
4576                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4577                                 if (r_shadow_glossexact.integer)
4578                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4579                         }
4580                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4581                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4582                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4583                         else
4584                                 R_Mesh_ColorPointer(NULL, 0, 0);
4585                 }
4586                 else if (r_glsl_deluxemapping.integer >= 2)
4587                 {
4588                         // fake deluxemapping (uniform light direction in tangentspace)
4589                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4590                         permutation |= SHADERPERMUTATION_DIFFUSE;
4591                         if (specularscale > 0)
4592                         {
4593                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4594                                 if (r_shadow_glossexact.integer)
4595                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4596                         }
4597                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4598                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4599                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4600                         else
4601                                 R_Mesh_ColorPointer(NULL, 0, 0);
4602                 }
4603                 else if (rsurface.uselightmaptexture)
4604                 {
4605                         // ordinary lightmapping (q1bsp, q3bsp)
4606                         mode = SHADERMODE_LIGHTMAP;
4607                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4608                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4609                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4610                         else
4611                                 R_Mesh_ColorPointer(NULL, 0, 0);
4612                 }
4613                 else
4614                 {
4615                         // ordinary vertex coloring (q3bsp)
4616                         mode = SHADERMODE_VERTEXCOLOR;
4617                         R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4618                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4619                 }
4620                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4621                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4622                 {
4623                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4624                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4625                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4626                 }
4627                 else
4628                 {
4629                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4630                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4631                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4632                 }
4633                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4634                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4635         }
4636         switch(vid.renderpath)
4637         {
4638         case RENDERPATH_GL20:
4639                 R_SetupShader_SetPermutationGLSL(mode, permutation);
4640                 if (mode == SHADERMODE_LIGHTSOURCE)
4641                 {
4642                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
4643                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
4644                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
4645                         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);
4646                         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);
4647                         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);
4648         
4649                         // additive passes are only darkened by fog, not tinted
4650                         if (r_glsl_permutation->loc_FogColor >= 0)
4651                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4652                         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]);
4653                         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]);
4654                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4655                 }
4656                 else
4657                 {
4658                         if (mode == SHADERMODE_FLATCOLOR)
4659                         {
4660                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
4661                         }
4662                         else if (mode == SHADERMODE_LIGHTDIRECTION)
4663                         {
4664                                 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]);
4665                                 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]);
4666                                 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);
4667                                 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);
4668                                 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);
4669                                 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]);
4670                                 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]);
4671                         }
4672                         else
4673                         {
4674                                 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]);
4675                                 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]);
4676                                 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);
4677                                 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);
4678                                 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);
4679                         }
4680                         // additive passes are only darkened by fog, not tinted
4681                         if (r_glsl_permutation->loc_FogColor >= 0)
4682                         {
4683                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4684                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4685                                 else
4686                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4687                         }
4688                         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);
4689                         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]);
4690                         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]);
4691                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
4692                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
4693                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
4694                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
4695                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4696                 }
4697                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
4698                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
4699                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
4700                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
4701                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
4702                 if (r_glsl_permutation->loc_Color_Pants >= 0)
4703                 {
4704                         if (rsurface.texture->pantstexture)
4705                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4706                         else
4707                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
4708                 }
4709                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
4710                 {
4711                         if (rsurface.texture->shirttexture)
4712                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4713                         else
4714                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
4715                 }
4716                 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]);
4717                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
4718                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
4719                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
4720                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
4721                 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]);
4722
4723         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
4724         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
4725         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
4726                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
4727                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
4728                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
4729                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
4730                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
4731                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
4732                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
4733                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
4734                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
4735                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
4736                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
4737                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_white                                     );
4738                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_blanknormalmap                            );
4739                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
4740                 if (r_glsl_permutation->loc_Texture_Refraction      >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , r_texture_white                                     );
4741                 if (r_glsl_permutation->loc_Texture_Reflection      >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , r_texture_white                                     );
4742                 if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
4743                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
4744                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
4745                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
4746                 if (rsurface.rtlight)
4747                 {
4748                         if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
4749                         if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT     , r_shadow_shadowmaprectangletexture                  );
4750                         if (r_shadow_usingshadowmapcube)
4751                                 if (r_glsl_permutation->loc_Texture_ShadowMapCube   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE     , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
4752                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D       , r_shadow_shadowmap2dtexture                         );
4753                         if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
4754                 }
4755                 CHECKGLERROR
4756                 break;
4757         case RENDERPATH_CGGL:
4758 #ifdef SUPPORTCG
4759                 R_SetupShader_SetPermutationCG(mode, permutation);
4760                 if (mode == SHADERMODE_LIGHTSOURCE)
4761                 {
4762                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
4763                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4764                 }
4765                 else
4766                 {
4767                         if (mode == SHADERMODE_LIGHTDIRECTION)
4768                         {
4769                                 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
4770                         }
4771                 }
4772                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
4773                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
4774                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4775                 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
4776                 CHECKGLERROR
4777
4778                 if (mode == SHADERMODE_LIGHTSOURCE)
4779                 {
4780                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4781                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
4782                         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
4783                         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
4784                         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
4785
4786                         // additive passes are only darkened by fog, not tinted
4787                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
4788                         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
4789                         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
4790                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4791                 }
4792                 else
4793                 {
4794                         if (mode == SHADERMODE_FLATCOLOR)
4795                         {
4796                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);CHECKCGERROR
4797                         }
4798                         else if (mode == SHADERMODE_LIGHTDIRECTION)
4799                         {
4800                                 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
4801                                 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
4802                                 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
4803                                 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
4804                                 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
4805                                 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
4806                                 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
4807                         }
4808                         else
4809                         {
4810                                 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
4811                                 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
4812                                 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
4813                                 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
4814                                 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
4815                         }
4816                         // additive passes are only darkened by fog, not tinted
4817                         if (r_cg_permutation->fp_FogColor)
4818                         {
4819                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4820                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
4821                                 else
4822                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4823                                 CHECKCGERROR
4824                         }
4825                         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
4826                         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
4827                         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
4828                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
4829                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
4830                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
4831                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
4832                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4833                 }
4834                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
4835                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
4836                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4837                 if (r_cg_permutation->fp_Color_Pants)
4838                 {
4839                         if (rsurface.texture->pantstexture)
4840                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4841                         else
4842                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
4843                         CHECKCGERROR
4844                 }
4845                 if (r_cg_permutation->fp_Color_Shirt)
4846                 {
4847                         if (rsurface.texture->shirttexture)
4848                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4849                         else
4850                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
4851                         CHECKCGERROR
4852                 }
4853                 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
4854                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
4855                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
4856                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
4857                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
4858                 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
4859
4860         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
4861         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
4862         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
4863                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
4864                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
4865                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
4866                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
4867                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
4868                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
4869                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
4870                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
4871                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
4872                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
4873                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
4874                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , r_texture_white                                     );CHECKCGERROR
4875                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , r_texture_blanknormalmap                            );CHECKCGERROR
4876                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
4877                 if (r_cg_permutation->fp_Texture_Refraction     ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction     , r_texture_white                                     );CHECKCGERROR
4878                 if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , r_texture_white                                     );CHECKCGERROR
4879                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
4880                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
4881                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
4882                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
4883                 if (rsurface.rtlight)
4884                 {
4885                         if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
4886                         if (r_cg_permutation->fp_Texture_ShadowMapRect  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
4887                         if (r_shadow_usingshadowmapcube)
4888                                 if (r_cg_permutation->fp_Texture_ShadowMapCube  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
4889                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
4890                         if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
4891                 }
4892
4893                 CHECKGLERROR
4894 #endif
4895                 break;
4896         case RENDERPATH_GL13:
4897         case RENDERPATH_GL11:
4898                 break;
4899         }
4900 }
4901
4902 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
4903 {
4904         // select a permutation of the lighting shader appropriate to this
4905         // combination of texture, entity, light source, and fogging, only use the
4906         // minimum features necessary to avoid wasting rendering time in the
4907         // fragment shader on features that are not being used
4908         unsigned int permutation = 0;
4909         unsigned int mode = 0;
4910         const float *lightcolorbase = rtlight->currentcolor;
4911         float ambientscale = rtlight->ambientscale;
4912         float diffusescale = rtlight->diffusescale;
4913         float specularscale = rtlight->specularscale;
4914         // this is the location of the light in view space
4915         vec3_t viewlightorigin;
4916         // this transforms from view space (camera) to light space (cubemap)
4917         matrix4x4_t viewtolight;
4918         matrix4x4_t lighttoview;
4919         float viewtolight16f[16];
4920         float range = 1.0f / r_shadow_deferred_8bitrange.value;
4921         // light source
4922         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
4923         if (rtlight->currentcubemap != r_texture_whitecube)
4924                 permutation |= SHADERPERMUTATION_CUBEFILTER;
4925         if (diffusescale > 0)
4926                 permutation |= SHADERPERMUTATION_DIFFUSE;
4927         if (specularscale > 0)
4928         {
4929                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4930                 if (r_shadow_glossexact.integer)
4931                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4932         }
4933         if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4934         {
4935                 if (r_shadow_usingshadowmaprect)
4936                         permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4937                 if (r_shadow_usingshadowmap2d)
4938                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4939                 if (r_shadow_usingshadowmapcube)
4940                         permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4941                 else if(r_shadow_shadowmapvsdct)
4942                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4943
4944                 if (r_shadow_shadowmapsampler)
4945                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4946                 if (r_shadow_shadowmappcf > 1)
4947                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4948                 else if (r_shadow_shadowmappcf)
4949                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4950         }
4951         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
4952         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
4953         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
4954         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
4955         switch(vid.renderpath)
4956         {
4957         case RENDERPATH_GL20:
4958                 R_SetupShader_SetPermutationGLSL(mode, permutation);
4959                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
4960                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
4961                 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);
4962                 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);
4963                 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);
4964                 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]);
4965                 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]);
4966                 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));
4967                 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]);
4968
4969                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
4970                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
4971                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
4972                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
4973                 if (r_glsl_permutation->loc_Texture_ShadowMapRect     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT      , r_shadow_shadowmaprectangletexture                  );
4974                 if (r_shadow_usingshadowmapcube)
4975                         if (r_glsl_permutation->loc_Texture_ShadowMapCube     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE      , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
4976                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
4977                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
4978                 break;
4979         case RENDERPATH_CGGL:
4980 #ifdef SUPPORTCG
4981                 R_SetupShader_SetPermutationCG(mode, permutation);
4982                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
4983                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
4984                 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
4985                 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
4986                 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
4987                 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
4988                 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
4989                 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
4990                 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
4991
4992                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
4993                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
4994                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
4995                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
4996                 if (r_cg_permutation->fp_Texture_ShadowMapRect    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
4997                 if (r_shadow_usingshadowmapcube)
4998                         if (r_cg_permutation->fp_Texture_ShadowMapCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
4999                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5000                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
5001 #endif
5002                 break;
5003         case RENDERPATH_GL13:
5004         case RENDERPATH_GL11:
5005                 break;
5006         }
5007 }
5008
5009 #define SKINFRAME_HASH 1024
5010
5011 typedef struct
5012 {
5013         int loadsequence; // incremented each level change
5014         memexpandablearray_t array;
5015         skinframe_t *hash[SKINFRAME_HASH];
5016 }
5017 r_skinframe_t;
5018 r_skinframe_t r_skinframe;
5019
5020 void R_SkinFrame_PrepareForPurge(void)
5021 {
5022         r_skinframe.loadsequence++;
5023         // wrap it without hitting zero
5024         if (r_skinframe.loadsequence >= 200)
5025                 r_skinframe.loadsequence = 1;
5026 }
5027
5028 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5029 {
5030         if (!skinframe)
5031                 return;
5032         // mark the skinframe as used for the purging code
5033         skinframe->loadsequence = r_skinframe.loadsequence;
5034 }
5035
5036 void R_SkinFrame_Purge(void)
5037 {
5038         int i;
5039         skinframe_t *s;
5040         for (i = 0;i < SKINFRAME_HASH;i++)
5041         {
5042                 for (s = r_skinframe.hash[i];s;s = s->next)
5043                 {
5044                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5045                         {
5046                                 if (s->merged == s->base)
5047                                         s->merged = NULL;
5048                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5049                                 R_PurgeTexture(s->stain );s->stain  = NULL;
5050                                 R_PurgeTexture(s->merged);s->merged = NULL;
5051                                 R_PurgeTexture(s->base  );s->base   = NULL;
5052                                 R_PurgeTexture(s->pants );s->pants  = NULL;
5053                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
5054                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
5055                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
5056                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
5057                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
5058                                 s->loadsequence = 0;
5059                         }
5060                 }
5061         }
5062 }
5063
5064 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5065         skinframe_t *item;
5066         char basename[MAX_QPATH];
5067
5068         Image_StripImageExtension(name, basename, sizeof(basename));
5069
5070         if( last == NULL ) {
5071                 int hashindex;
5072                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5073                 item = r_skinframe.hash[hashindex];
5074         } else {
5075                 item = last->next;
5076         }
5077
5078         // linearly search through the hash bucket
5079         for( ; item ; item = item->next ) {
5080                 if( !strcmp( item->basename, basename ) ) {
5081                         return item;
5082                 }
5083         }
5084         return NULL;
5085 }
5086
5087 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5088 {
5089         skinframe_t *item;
5090         int hashindex;
5091         char basename[MAX_QPATH];
5092
5093         Image_StripImageExtension(name, basename, sizeof(basename));
5094
5095         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5096         for (item = r_skinframe.hash[hashindex];item;item = item->next)
5097                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5098                         break;
5099
5100         if (!item) {
5101                 rtexture_t *dyntexture;
5102                 // check whether its a dynamic texture
5103                 dyntexture = CL_GetDynTexture( basename );
5104                 if (!add && !dyntexture)
5105                         return NULL;
5106                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5107                 memset(item, 0, sizeof(*item));
5108                 strlcpy(item->basename, basename, sizeof(item->basename));
5109                 item->base = dyntexture; // either NULL or dyntexture handle
5110                 item->textureflags = textureflags;
5111                 item->comparewidth = comparewidth;
5112                 item->compareheight = compareheight;
5113                 item->comparecrc = comparecrc;
5114                 item->next = r_skinframe.hash[hashindex];
5115                 r_skinframe.hash[hashindex] = item;
5116         }
5117         else if( item->base == NULL )
5118         {
5119                 rtexture_t *dyntexture;
5120                 // check whether its a dynamic texture
5121                 // 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]
5122                 dyntexture = CL_GetDynTexture( basename );
5123                 item->base = dyntexture; // either NULL or dyntexture handle
5124         }
5125
5126         R_SkinFrame_MarkUsed(item);
5127         return item;
5128 }
5129
5130 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5131         { \
5132                 unsigned long long avgcolor[5], wsum; \
5133                 int pix, comp, w; \
5134                 avgcolor[0] = 0; \
5135                 avgcolor[1] = 0; \
5136                 avgcolor[2] = 0; \
5137                 avgcolor[3] = 0; \
5138                 avgcolor[4] = 0; \
5139                 wsum = 0; \
5140                 for(pix = 0; pix < cnt; ++pix) \
5141                 { \
5142                         w = 0; \
5143                         for(comp = 0; comp < 3; ++comp) \
5144                                 w += getpixel; \
5145                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5146                         { \
5147                                 ++wsum; \
5148                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5149                                 w = getpixel; \
5150                                 for(comp = 0; comp < 3; ++comp) \
5151                                         avgcolor[comp] += getpixel * w; \
5152                                 avgcolor[3] += w; \
5153                         } \
5154                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5155                         avgcolor[4] += getpixel; \
5156                 } \
5157                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5158                         avgcolor[3] = 1; \
5159                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5160                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5161                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5162                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5163         }
5164
5165 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5166 {
5167         int j;
5168         unsigned char *pixels;
5169         unsigned char *bumppixels;
5170         unsigned char *basepixels = NULL;
5171         int basepixels_width = 0;
5172         int basepixels_height = 0;
5173         skinframe_t *skinframe;
5174         rtexture_t *ddsbase = NULL;
5175         qboolean ddshasalpha = false;
5176         float ddsavgcolor[4];
5177         char basename[MAX_QPATH];
5178
5179         if (cls.state == ca_dedicated)
5180                 return NULL;
5181
5182         // return an existing skinframe if already loaded
5183         // if loading of the first image fails, don't make a new skinframe as it
5184         // would cause all future lookups of this to be missing
5185         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5186         if (skinframe && skinframe->base)
5187                 return skinframe;
5188
5189         Image_StripImageExtension(name, basename, sizeof(basename));
5190
5191         // check for DDS texture file first
5192         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor)))
5193         {
5194                 basepixels = loadimagepixelsbgra(name, complain, true);
5195                 if (basepixels == NULL)
5196                         return NULL;
5197         }
5198
5199         if (developer_loading.integer)
5200                 Con_Printf("loading skin \"%s\"\n", name);
5201
5202         // we've got some pixels to store, so really allocate this new texture now
5203         if (!skinframe)
5204                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5205         skinframe->stain = NULL;
5206         skinframe->merged = NULL;
5207         skinframe->base = NULL;
5208         skinframe->pants = NULL;
5209         skinframe->shirt = NULL;
5210         skinframe->nmap = NULL;
5211         skinframe->gloss = NULL;
5212         skinframe->glow = NULL;
5213         skinframe->fog = NULL;
5214         skinframe->hasalpha = false;
5215
5216         if (ddsbase)
5217         {
5218                 skinframe->base = ddsbase;
5219                 skinframe->hasalpha = ddshasalpha;
5220                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5221                 if (r_loadfog && skinframe->hasalpha)
5222                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5223                 //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]);
5224         }
5225         else
5226         {
5227                 basepixels_width = image_width;
5228                 basepixels_height = image_height;
5229                 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);
5230                 if (textureflags & TEXF_ALPHA)
5231                 {
5232                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5233                         {
5234                                 if (basepixels[j] < 255)
5235                                 {
5236                                         skinframe->hasalpha = true;
5237                                         break;
5238                                 }
5239                         }
5240                         if (r_loadfog && skinframe->hasalpha)
5241                         {
5242                                 // has transparent pixels
5243                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5244                                 for (j = 0;j < image_width * image_height * 4;j += 4)
5245                                 {
5246                                         pixels[j+0] = 255;
5247                                         pixels[j+1] = 255;
5248                                         pixels[j+2] = 255;
5249                                         pixels[j+3] = basepixels[j+3];
5250                                 }
5251                                 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);
5252                                 Mem_Free(pixels);
5253                         }
5254                 }
5255                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5256                 //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]);
5257                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5258                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true);
5259                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
5260                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true);
5261         }
5262
5263         if (r_loaddds)
5264         {
5265                 if (r_loadnormalmap)
5266                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5267                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL);
5268                 if (r_loadgloss)
5269                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL);
5270                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL);
5271                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL);
5272         }
5273
5274         // _norm is the name used by tenebrae and has been adopted as standard
5275         if (r_loadnormalmap && skinframe->nmap == NULL)
5276         {
5277                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
5278                 {
5279                         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);
5280                         Mem_Free(pixels);
5281                         pixels = NULL;
5282                 }
5283                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
5284                 {
5285                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5286                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5287                         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);
5288                         Mem_Free(pixels);
5289                         Mem_Free(bumppixels);
5290                 }
5291                 else if (r_shadow_bumpscale_basetexture.value > 0)
5292                 {
5293                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5294                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5295                         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);
5296                         Mem_Free(pixels);
5297                 }
5298                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
5299                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true);
5300         }
5301
5302         // _luma is supported only for tenebrae compatibility
5303         // _glow is the preferred name
5304         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false))))
5305         {
5306                 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);
5307                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
5308                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true);
5309                 Mem_Free(pixels);pixels = NULL;
5310         }
5311
5312         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false)))
5313         {
5314                 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);
5315                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
5316                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true);
5317                 Mem_Free(pixels);
5318                 pixels = NULL;
5319         }
5320
5321         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false)))
5322         {
5323                 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);
5324                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
5325                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true);
5326                 Mem_Free(pixels);
5327                 pixels = NULL;
5328         }
5329
5330         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false)))
5331         {
5332                 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);
5333                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
5334                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true);
5335                 Mem_Free(pixels);
5336                 pixels = NULL;
5337         }
5338
5339         if (basepixels)
5340                 Mem_Free(basepixels);
5341
5342         return skinframe;
5343 }
5344
5345 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
5346 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
5347 {
5348         int i;
5349         unsigned char *temp1, *temp2;
5350         skinframe_t *skinframe;
5351
5352         if (cls.state == ca_dedicated)
5353                 return NULL;
5354
5355         // if already loaded just return it, otherwise make a new skinframe
5356         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
5357         if (skinframe && skinframe->base)
5358                 return skinframe;
5359
5360         skinframe->stain = NULL;
5361         skinframe->merged = NULL;
5362         skinframe->base = NULL;
5363         skinframe->pants = NULL;
5364         skinframe->shirt = NULL;
5365         skinframe->nmap = NULL;
5366         skinframe->gloss = NULL;
5367         skinframe->glow = NULL;
5368         skinframe->fog = NULL;
5369         skinframe->hasalpha = false;
5370
5371         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5372         if (!skindata)
5373                 return NULL;
5374
5375         if (developer_loading.integer)
5376                 Con_Printf("loading 32bit skin \"%s\"\n", name);
5377
5378         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
5379         {
5380                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5381                 temp2 = temp1 + width * height * 4;
5382                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5383                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5384                 Mem_Free(temp1);
5385         }
5386         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5387         if (textureflags & TEXF_ALPHA)
5388         {
5389                 for (i = 3;i < width * height * 4;i += 4)
5390                 {
5391                         if (skindata[i] < 255)
5392                         {
5393                                 skinframe->hasalpha = true;
5394                                 break;
5395                         }
5396                 }
5397                 if (r_loadfog && skinframe->hasalpha)
5398                 {
5399                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
5400                         memcpy(fogpixels, skindata, width * height * 4);
5401                         for (i = 0;i < width * height * 4;i += 4)
5402                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
5403                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5404                         Mem_Free(fogpixels);
5405                 }
5406         }
5407
5408         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
5409         //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]);
5410
5411         return skinframe;
5412 }
5413
5414 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
5415 {
5416         int i;
5417         int featuresmask;
5418         skinframe_t *skinframe;
5419
5420         if (cls.state == ca_dedicated)
5421                 return NULL;
5422
5423         // if already loaded just return it, otherwise make a new skinframe
5424         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5425         if (skinframe && skinframe->base)
5426                 return skinframe;
5427
5428         skinframe->stain = NULL;
5429         skinframe->merged = NULL;
5430         skinframe->base = NULL;
5431         skinframe->pants = NULL;
5432         skinframe->shirt = NULL;
5433         skinframe->nmap = NULL;
5434         skinframe->gloss = NULL;
5435         skinframe->glow = NULL;
5436         skinframe->fog = NULL;
5437         skinframe->hasalpha = false;
5438
5439         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5440         if (!skindata)
5441                 return NULL;
5442
5443         if (developer_loading.integer)
5444                 Con_Printf("loading quake skin \"%s\"\n", name);
5445
5446         // 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)
5447         skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
5448         memcpy(skinframe->qpixels, skindata, width*height);
5449         skinframe->qwidth = width;
5450         skinframe->qheight = height;
5451
5452         featuresmask = 0;
5453         for (i = 0;i < width * height;i++)
5454                 featuresmask |= palette_featureflags[skindata[i]];
5455
5456         skinframe->hasalpha = false;
5457         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
5458         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
5459         skinframe->qgeneratemerged = true;
5460         skinframe->qgeneratebase = skinframe->qhascolormapping;
5461         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
5462
5463         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
5464         //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]);
5465
5466         return skinframe;
5467 }
5468
5469 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
5470 {
5471         int width;
5472         int height;
5473         unsigned char *skindata;
5474
5475         if (!skinframe->qpixels)
5476                 return;
5477
5478         if (!skinframe->qhascolormapping)
5479                 colormapped = false;
5480
5481         if (colormapped)
5482         {
5483                 if (!skinframe->qgeneratebase)
5484                         return;
5485         }
5486         else
5487         {
5488                 if (!skinframe->qgeneratemerged)
5489                         return;
5490         }
5491
5492         width = skinframe->qwidth;
5493         height = skinframe->qheight;
5494         skindata = skinframe->qpixels;
5495
5496         if (skinframe->qgeneratenmap)
5497         {
5498                 unsigned char *temp1, *temp2;
5499                 skinframe->qgeneratenmap = false;
5500                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5501                 temp2 = temp1 + width * height * 4;
5502                 // use either a custom palette or the quake palette
5503                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
5504                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5505                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5506                 Mem_Free(temp1);
5507         }
5508
5509         if (skinframe->qgenerateglow)
5510         {
5511                 skinframe->qgenerateglow = false;
5512                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
5513         }
5514
5515         if (colormapped)
5516         {
5517                 skinframe->qgeneratebase = false;
5518                 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);
5519                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
5520                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
5521         }
5522         else
5523         {
5524                 skinframe->qgeneratemerged = false;
5525                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
5526         }
5527
5528         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
5529         {
5530                 Mem_Free(skinframe->qpixels);
5531                 skinframe->qpixels = NULL;
5532         }
5533 }
5534
5535 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)
5536 {
5537         int i;
5538         skinframe_t *skinframe;
5539
5540         if (cls.state == ca_dedicated)
5541                 return NULL;
5542
5543         // if already loaded just return it, otherwise make a new skinframe
5544         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5545         if (skinframe && skinframe->base)
5546                 return skinframe;
5547
5548         skinframe->stain = NULL;
5549         skinframe->merged = NULL;
5550         skinframe->base = NULL;
5551         skinframe->pants = NULL;
5552         skinframe->shirt = NULL;
5553         skinframe->nmap = NULL;
5554         skinframe->gloss = NULL;
5555         skinframe->glow = NULL;
5556         skinframe->fog = NULL;
5557         skinframe->hasalpha = false;
5558
5559         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5560         if (!skindata)
5561                 return NULL;
5562
5563         if (developer_loading.integer)
5564                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
5565
5566         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
5567         if (textureflags & TEXF_ALPHA)
5568         {
5569                 for (i = 0;i < width * height;i++)
5570                 {
5571                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
5572                         {
5573                                 skinframe->hasalpha = true;
5574                                 break;
5575                         }
5576                 }
5577                 if (r_loadfog && skinframe->hasalpha)
5578                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
5579         }
5580
5581         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
5582         //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]);
5583
5584         return skinframe;
5585 }
5586
5587 skinframe_t *R_SkinFrame_LoadMissing(void)
5588 {
5589         skinframe_t *skinframe;
5590
5591         if (cls.state == ca_dedicated)
5592                 return NULL;
5593
5594         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
5595         skinframe->stain = NULL;
5596         skinframe->merged = NULL;
5597         skinframe->base = NULL;
5598         skinframe->pants = NULL;
5599         skinframe->shirt = NULL;
5600         skinframe->nmap = NULL;
5601         skinframe->gloss = NULL;
5602         skinframe->glow = NULL;
5603         skinframe->fog = NULL;
5604         skinframe->hasalpha = false;
5605
5606         skinframe->avgcolor[0] = rand() / RAND_MAX;
5607         skinframe->avgcolor[1] = rand() / RAND_MAX;
5608         skinframe->avgcolor[2] = rand() / RAND_MAX;
5609         skinframe->avgcolor[3] = 1;
5610
5611         return skinframe;
5612 }
5613
5614 void R_Main_FreeViewCache(void)
5615 {
5616         if (r_refdef.viewcache.entityvisible)
5617                 Mem_Free(r_refdef.viewcache.entityvisible);
5618         if (r_refdef.viewcache.world_pvsbits)
5619                 Mem_Free(r_refdef.viewcache.world_pvsbits);
5620         if (r_refdef.viewcache.world_leafvisible)
5621                 Mem_Free(r_refdef.viewcache.world_leafvisible);
5622         if (r_refdef.viewcache.world_surfacevisible)
5623                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
5624         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
5625 }
5626
5627 void R_Main_ResizeViewCache(void)
5628 {
5629         int numentities = r_refdef.scene.numentities;
5630         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
5631         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
5632         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
5633         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
5634         if (r_refdef.viewcache.maxentities < numentities)
5635         {
5636                 r_refdef.viewcache.maxentities = numentities;
5637                 if (r_refdef.viewcache.entityvisible)
5638                         Mem_Free(r_refdef.viewcache.entityvisible);
5639                 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
5640         }
5641         if (r_refdef.viewcache.world_numclusters != numclusters)
5642         {
5643                 r_refdef.viewcache.world_numclusters = numclusters;
5644                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
5645                 if (r_refdef.viewcache.world_pvsbits)
5646                         Mem_Free(r_refdef.viewcache.world_pvsbits);
5647                 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
5648         }
5649         if (r_refdef.viewcache.world_numleafs != numleafs)
5650         {
5651                 r_refdef.viewcache.world_numleafs = numleafs;
5652                 if (r_refdef.viewcache.world_leafvisible)
5653                         Mem_Free(r_refdef.viewcache.world_leafvisible);
5654                 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
5655         }
5656         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
5657         {
5658                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
5659                 if (r_refdef.viewcache.world_surfacevisible)
5660                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
5661                 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
5662         }
5663 }
5664
5665 extern rtexture_t *loadingscreentexture;
5666 void gl_main_start(void)
5667 {
5668         loadingscreentexture = NULL;
5669         r_texture_blanknormalmap = NULL;
5670         r_texture_white = NULL;
5671         r_texture_grey128 = NULL;
5672         r_texture_black = NULL;
5673         r_texture_whitecube = NULL;
5674         r_texture_normalizationcube = NULL;
5675         r_texture_fogattenuation = NULL;
5676         r_texture_gammaramps = NULL;
5677
5678         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
5679         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
5680
5681         switch(vid.renderpath)
5682         {
5683         case RENDERPATH_GL20:
5684         case RENDERPATH_CGGL:
5685                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5686                 Cvar_SetValueQuick(&gl_combine, 1);
5687                 Cvar_SetValueQuick(&r_glsl, 1);
5688                 r_loadnormalmap = true;
5689                 r_loadgloss = true;
5690                 r_loadfog = false;
5691                 break;
5692         case RENDERPATH_GL13:
5693                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5694                 Cvar_SetValueQuick(&gl_combine, 1);
5695                 Cvar_SetValueQuick(&r_glsl, 0);
5696                 r_loadnormalmap = false;
5697                 r_loadgloss = false;
5698                 r_loadfog = true;
5699                 break;
5700         case RENDERPATH_GL11:
5701                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5702                 Cvar_SetValueQuick(&gl_combine, 0);
5703                 Cvar_SetValueQuick(&r_glsl, 0);
5704                 r_loadnormalmap = false;
5705                 r_loadgloss = false;
5706                 r_loadfog = true;
5707                 break;
5708         }
5709
5710         R_AnimCache_Free();
5711         R_FrameData_Reset();
5712
5713         r_numqueries = 0;
5714         r_maxqueries = 0;
5715         memset(r_queries, 0, sizeof(r_queries));
5716
5717         r_qwskincache = NULL;
5718         r_qwskincache_size = 0;
5719
5720         // set up r_skinframe loading system for textures
5721         memset(&r_skinframe, 0, sizeof(r_skinframe));
5722         r_skinframe.loadsequence = 1;
5723         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
5724
5725         r_main_texturepool = R_AllocTexturePool();
5726         R_BuildBlankTextures();
5727         R_BuildNoTexture();
5728         if (vid.support.arb_texture_cube_map)
5729         {
5730                 R_BuildWhiteCube();
5731                 R_BuildNormalizationCube();
5732         }
5733         r_texture_fogattenuation = NULL;
5734         r_texture_gammaramps = NULL;
5735         //r_texture_fogintensity = NULL;
5736         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
5737         memset(&r_waterstate, 0, sizeof(r_waterstate));
5738         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5739         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
5740 #ifdef SUPPORTCG
5741         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5742         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
5743 #endif
5744         memset(&r_svbsp, 0, sizeof (r_svbsp));
5745
5746         r_refdef.fogmasktable_density = 0;
5747 }
5748
5749 void gl_main_shutdown(void)
5750 {
5751         R_AnimCache_Free();
5752         R_FrameData_Reset();
5753
5754         R_Main_FreeViewCache();
5755
5756         if (r_maxqueries)
5757                 qglDeleteQueriesARB(r_maxqueries, r_queries);
5758
5759         r_numqueries = 0;
5760         r_maxqueries = 0;
5761         memset(r_queries, 0, sizeof(r_queries));
5762
5763         r_qwskincache = NULL;
5764         r_qwskincache_size = 0;
5765
5766         // clear out the r_skinframe state
5767         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
5768         memset(&r_skinframe, 0, sizeof(r_skinframe));
5769
5770         if (r_svbsp.nodes)
5771                 Mem_Free(r_svbsp.nodes);
5772         memset(&r_svbsp, 0, sizeof (r_svbsp));
5773         R_FreeTexturePool(&r_main_texturepool);
5774         loadingscreentexture = NULL;
5775         r_texture_blanknormalmap = NULL;
5776         r_texture_white = NULL;
5777         r_texture_grey128 = NULL;
5778         r_texture_black = NULL;
5779         r_texture_whitecube = NULL;
5780         r_texture_normalizationcube = NULL;
5781         r_texture_fogattenuation = NULL;
5782         r_texture_gammaramps = NULL;
5783         //r_texture_fogintensity = NULL;
5784         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
5785         memset(&r_waterstate, 0, sizeof(r_waterstate));
5786         R_GLSL_Restart_f();
5787 }
5788
5789 extern void CL_ParseEntityLump(char *entitystring);
5790 void gl_main_newmap(void)
5791 {
5792         // FIXME: move this code to client
5793         int l;
5794         char *entities, entname[MAX_QPATH];
5795         if (r_qwskincache)
5796                 Mem_Free(r_qwskincache);
5797         r_qwskincache = NULL;
5798         r_qwskincache_size = 0;
5799         if (cl.worldmodel)
5800         {
5801                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
5802                 l = (int)strlen(entname) - 4;
5803                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
5804                 {
5805                         memcpy(entname + l, ".ent", 5);
5806                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
5807                         {
5808                                 CL_ParseEntityLump(entities);
5809                                 Mem_Free(entities);
5810                                 return;
5811                         }
5812                 }
5813                 if (cl.worldmodel->brush.entities)
5814                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
5815         }
5816         R_Main_FreeViewCache();
5817
5818         R_FrameData_Reset();
5819 }
5820
5821 void GL_Main_Init(void)
5822 {
5823         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
5824
5825         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
5826         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
5827         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
5828         if (gamemode == GAME_NEHAHRA)
5829         {
5830                 Cvar_RegisterVariable (&gl_fogenable);
5831                 Cvar_RegisterVariable (&gl_fogdensity);
5832                 Cvar_RegisterVariable (&gl_fogred);
5833                 Cvar_RegisterVariable (&gl_foggreen);
5834                 Cvar_RegisterVariable (&gl_fogblue);
5835                 Cvar_RegisterVariable (&gl_fogstart);
5836                 Cvar_RegisterVariable (&gl_fogend);
5837                 Cvar_RegisterVariable (&gl_skyclip);
5838         }
5839         Cvar_RegisterVariable(&r_motionblur);
5840         Cvar_RegisterVariable(&r_motionblur_maxblur);
5841         Cvar_RegisterVariable(&r_motionblur_bmin);
5842         Cvar_RegisterVariable(&r_motionblur_vmin);
5843         Cvar_RegisterVariable(&r_motionblur_vmax);
5844         Cvar_RegisterVariable(&r_motionblur_vcoeff);
5845         Cvar_RegisterVariable(&r_motionblur_randomize);
5846         Cvar_RegisterVariable(&r_damageblur);
5847         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
5848         Cvar_RegisterVariable(&r_equalize_entities_minambient);
5849         Cvar_RegisterVariable(&r_equalize_entities_by);
5850         Cvar_RegisterVariable(&r_equalize_entities_to);
5851         Cvar_RegisterVariable(&r_depthfirst);
5852         Cvar_RegisterVariable(&r_useinfinitefarclip);
5853         Cvar_RegisterVariable(&r_farclip_base);
5854         Cvar_RegisterVariable(&r_farclip_world);
5855         Cvar_RegisterVariable(&r_nearclip);
5856         Cvar_RegisterVariable(&r_showbboxes);
5857         Cvar_RegisterVariable(&r_showsurfaces);
5858         Cvar_RegisterVariable(&r_showtris);
5859         Cvar_RegisterVariable(&r_shownormals);
5860         Cvar_RegisterVariable(&r_showlighting);
5861         Cvar_RegisterVariable(&r_showshadowvolumes);
5862         Cvar_RegisterVariable(&r_showcollisionbrushes);
5863         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
5864         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
5865         Cvar_RegisterVariable(&r_showdisabledepthtest);
5866         Cvar_RegisterVariable(&r_drawportals);
5867         Cvar_RegisterVariable(&r_drawentities);
5868         Cvar_RegisterVariable(&r_cullentities_trace);
5869         Cvar_RegisterVariable(&r_cullentities_trace_samples);
5870         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
5871         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
5872         Cvar_RegisterVariable(&r_cullentities_trace_delay);
5873         Cvar_RegisterVariable(&r_drawviewmodel);
5874         Cvar_RegisterVariable(&r_speeds);
5875         Cvar_RegisterVariable(&r_fullbrights);
5876         Cvar_RegisterVariable(&r_wateralpha);
5877         Cvar_RegisterVariable(&r_dynamic);
5878         Cvar_RegisterVariable(&r_fullbright);
5879         Cvar_RegisterVariable(&r_shadows);
5880         Cvar_RegisterVariable(&r_shadows_darken);
5881         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
5882         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
5883         Cvar_RegisterVariable(&r_shadows_throwdistance);
5884         Cvar_RegisterVariable(&r_shadows_throwdirection);
5885         Cvar_RegisterVariable(&r_q1bsp_skymasking);
5886         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
5887         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
5888         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
5889         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
5890         Cvar_RegisterVariable(&r_fog_exp2);
5891         Cvar_RegisterVariable(&r_drawfog);
5892         Cvar_RegisterVariable(&r_transparentdepthmasking);
5893         Cvar_RegisterVariable(&r_texture_dds_load);
5894         Cvar_RegisterVariable(&r_texture_dds_save);
5895         Cvar_RegisterVariable(&r_textureunits);
5896         Cvar_RegisterVariable(&gl_combine);
5897         Cvar_RegisterVariable(&r_glsl);
5898         Cvar_RegisterVariable(&r_glsl_deluxemapping);
5899         Cvar_RegisterVariable(&r_glsl_offsetmapping);
5900         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
5901         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
5902         Cvar_RegisterVariable(&r_glsl_postprocess);
5903         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
5904         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
5905         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
5906         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
5907         Cvar_RegisterVariable(&r_water);
5908         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
5909         Cvar_RegisterVariable(&r_water_clippingplanebias);
5910         Cvar_RegisterVariable(&r_water_refractdistort);
5911         Cvar_RegisterVariable(&r_water_reflectdistort);
5912         Cvar_RegisterVariable(&r_lerpsprites);
5913         Cvar_RegisterVariable(&r_lerpmodels);
5914         Cvar_RegisterVariable(&r_lerplightstyles);
5915         Cvar_RegisterVariable(&r_waterscroll);
5916         Cvar_RegisterVariable(&r_bloom);
5917         Cvar_RegisterVariable(&r_bloom_colorscale);
5918         Cvar_RegisterVariable(&r_bloom_brighten);
5919         Cvar_RegisterVariable(&r_bloom_blur);
5920         Cvar_RegisterVariable(&r_bloom_resolution);
5921         Cvar_RegisterVariable(&r_bloom_colorexponent);
5922         Cvar_RegisterVariable(&r_bloom_colorsubtract);
5923         Cvar_RegisterVariable(&r_hdr);
5924         Cvar_RegisterVariable(&r_hdr_scenebrightness);
5925         Cvar_RegisterVariable(&r_hdr_glowintensity);
5926         Cvar_RegisterVariable(&r_hdr_range);
5927         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
5928         Cvar_RegisterVariable(&developer_texturelogging);
5929         Cvar_RegisterVariable(&gl_lightmaps);
5930         Cvar_RegisterVariable(&r_test);
5931         Cvar_RegisterVariable(&r_batchmode);
5932         Cvar_RegisterVariable(&r_glsl_saturation);
5933         Cvar_RegisterVariable(&r_framedatasize);
5934         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
5935                 Cvar_SetValue("r_fullbrights", 0);
5936         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
5937
5938         Cvar_RegisterVariable(&r_track_sprites);
5939         Cvar_RegisterVariable(&r_track_sprites_flags);
5940         Cvar_RegisterVariable(&r_track_sprites_scalew);
5941         Cvar_RegisterVariable(&r_track_sprites_scaleh);
5942 }
5943
5944 extern void R_Textures_Init(void);
5945 extern void GL_Draw_Init(void);
5946 extern void GL_Main_Init(void);
5947 extern void R_Shadow_Init(void);
5948 extern void R_Sky_Init(void);
5949 extern void GL_Surf_Init(void);
5950 extern void R_Particles_Init(void);
5951 extern void R_Explosion_Init(void);
5952 extern void gl_backend_init(void);
5953 extern void Sbar_Init(void);
5954 extern void R_LightningBeams_Init(void);
5955 extern void Mod_RenderInit(void);
5956 extern void Font_Init(void);
5957
5958 void Render_Init(void)
5959 {
5960         gl_backend_init();
5961         R_Textures_Init();
5962         GL_Main_Init();
5963         Font_Init();
5964         GL_Draw_Init();
5965         R_Shadow_Init();
5966         R_Sky_Init();
5967         GL_Surf_Init();
5968         Sbar_Init();
5969         R_Particles_Init();
5970         R_Explosion_Init();
5971         R_LightningBeams_Init();
5972         Mod_RenderInit();
5973 }
5974
5975 /*
5976 ===============
5977 GL_Init
5978 ===============
5979 */
5980 extern char *ENGINE_EXTENSIONS;
5981 void GL_Init (void)
5982 {
5983         gl_renderer = (const char *)qglGetString(GL_RENDERER);
5984         gl_vendor = (const char *)qglGetString(GL_VENDOR);
5985         gl_version = (const char *)qglGetString(GL_VERSION);
5986         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
5987
5988         if (!gl_extensions)
5989                 gl_extensions = "";
5990         if (!gl_platformextensions)
5991                 gl_platformextensions = "";
5992
5993         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
5994         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
5995         Con_Printf("GL_VERSION: %s\n", gl_version);
5996         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
5997         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
5998
5999         VID_CheckExtensions();
6000
6001         // LordHavoc: report supported extensions
6002         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
6003
6004         // clear to black (loading plaque will be seen over this)
6005         CHECKGLERROR
6006         qglClearColor(0,0,0,1);CHECKGLERROR
6007         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
6008 }
6009
6010 int R_CullBox(const vec3_t mins, const vec3_t maxs)
6011 {
6012         int i;
6013         mplane_t *p;
6014         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6015         {
6016                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
6017                 if (i == 4)
6018                         continue;
6019                 p = r_refdef.view.frustum + i;
6020                 switch(p->signbits)
6021                 {
6022                 default:
6023                 case 0:
6024                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6025                                 return true;
6026                         break;
6027                 case 1:
6028                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6029                                 return true;
6030                         break;
6031                 case 2:
6032                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6033                                 return true;
6034                         break;
6035                 case 3:
6036                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6037                                 return true;
6038                         break;
6039                 case 4:
6040                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6041                                 return true;
6042                         break;
6043                 case 5:
6044                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6045                                 return true;
6046                         break;
6047                 case 6:
6048                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6049                                 return true;
6050                         break;
6051                 case 7:
6052                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6053                                 return true;
6054                         break;
6055                 }
6056         }
6057         return false;
6058 }
6059
6060 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
6061 {
6062         int i;
6063         const mplane_t *p;
6064         for (i = 0;i < numplanes;i++)
6065         {
6066                 p = planes + i;
6067                 switch(p->signbits)
6068                 {
6069                 default:
6070                 case 0:
6071                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6072                                 return true;
6073                         break;
6074                 case 1:
6075                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6076                                 return true;
6077                         break;
6078                 case 2:
6079                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6080                                 return true;
6081                         break;
6082                 case 3:
6083                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6084                                 return true;
6085                         break;
6086                 case 4:
6087                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6088                                 return true;
6089                         break;
6090                 case 5:
6091                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6092                                 return true;
6093                         break;
6094                 case 6:
6095                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6096                                 return true;
6097                         break;
6098                 case 7:
6099                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6100                                 return true;
6101                         break;
6102                 }
6103         }
6104         return false;
6105 }
6106
6107 //==================================================================================
6108
6109 // LordHavoc: this stores temporary data used within the same frame
6110
6111 qboolean r_framedata_failed;
6112 static size_t r_framedata_size;
6113 static size_t r_framedata_current;
6114 static void *r_framedata_base;
6115
6116 void R_FrameData_Reset(void)
6117 {
6118         if (r_framedata_base)
6119                 Mem_Free(r_framedata_base);
6120         r_framedata_base = NULL;
6121         r_framedata_size = 0;
6122         r_framedata_current = 0;
6123         r_framedata_failed = false;
6124 }
6125
6126 void R_FrameData_NewFrame(void)
6127 {
6128         size_t wantedsize;
6129         if (r_framedata_failed)
6130                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
6131         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
6132         wantedsize = bound(65536, wantedsize, 128*1024*1024);
6133         if (r_framedata_size != wantedsize)
6134         {
6135                 r_framedata_size = wantedsize;
6136                 if (r_framedata_base)
6137                         Mem_Free(r_framedata_base);
6138                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
6139         }
6140         r_framedata_current = 0;
6141         r_framedata_failed = false;
6142 }
6143
6144 void *R_FrameData_Alloc(size_t size)
6145 {
6146         void *data;
6147
6148         // align to 16 byte boundary
6149         size = (size + 15) & ~15;
6150         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
6151         r_framedata_current += size;
6152
6153         // check overflow
6154         if (r_framedata_current > r_framedata_size)
6155                 r_framedata_failed = true;
6156
6157         // return NULL on everything after a failure
6158         if (r_framedata_failed)
6159                 return NULL;
6160
6161         return data;
6162 }
6163
6164 void *R_FrameData_Store(size_t size, void *data)
6165 {
6166         void *d = R_FrameData_Alloc(size);
6167         if (d)
6168                 memcpy(d, data, size);
6169         return d;
6170 }
6171
6172 //==================================================================================
6173
6174 // LordHavoc: animcache originally written by Echon, rewritten since then
6175
6176 /**
6177  * Animation cache prevents re-generating mesh data for an animated model
6178  * multiple times in one frame for lighting, shadowing, reflections, etc.
6179  */
6180
6181 void R_AnimCache_Free(void)
6182 {
6183 }
6184
6185 void R_AnimCache_ClearCache(void)
6186 {
6187         int i;
6188         entity_render_t *ent;
6189
6190         for (i = 0;i < r_refdef.scene.numentities;i++)
6191         {
6192                 ent = r_refdef.scene.entities[i];
6193                 ent->animcache_vertex3f = NULL;
6194                 ent->animcache_normal3f = NULL;
6195                 ent->animcache_svector3f = NULL;
6196                 ent->animcache_tvector3f = NULL;
6197         }
6198 }
6199
6200 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6201 {
6202         dp_model_t *model = ent->model;
6203         int numvertices;
6204         // see if it's already cached this frame
6205         if (ent->animcache_vertex3f)
6206         {
6207                 // add normals/tangents if needed
6208                 if (wantnormals || wanttangents)
6209                 {
6210                         if (ent->animcache_normal3f)
6211                                 wantnormals = false;
6212                         if (ent->animcache_svector3f)
6213                                 wanttangents = false;
6214                         if (wantnormals || wanttangents)
6215                         {
6216                                 numvertices = model->surfmesh.num_vertices;
6217                                 if (wantnormals)
6218                                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6219                                 if (wanttangents)
6220                                 {
6221                                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6222                                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6223                                 }
6224                                 if (!r_framedata_failed)
6225                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
6226                         }
6227                 }
6228         }
6229         else
6230         {
6231                 // see if this ent is worth caching
6232                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
6233                         return false;
6234                 // get some memory for this entity and generate mesh data
6235                 numvertices = model->surfmesh.num_vertices;
6236                 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6237                 if (wantnormals)
6238                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6239                 if (wanttangents)
6240                 {
6241                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6242                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6243                 }
6244                 if (!r_framedata_failed)
6245                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
6246         }
6247         return !r_framedata_failed;
6248 }
6249
6250 void R_AnimCache_CacheVisibleEntities(void)
6251 {
6252         int i;
6253         qboolean wantnormals = !r_showsurfaces.integer;
6254         qboolean wanttangents = !r_showsurfaces.integer;
6255
6256         switch(vid.renderpath)
6257         {
6258         case RENDERPATH_GL20:
6259         case RENDERPATH_CGGL:
6260                 break;
6261         case RENDERPATH_GL13:
6262         case RENDERPATH_GL11:
6263                 wanttangents = false;
6264                 break;
6265         }
6266
6267         // TODO: thread this
6268         // NOTE: R_PrepareRTLights() also caches entities
6269
6270         for (i = 0;i < r_refdef.scene.numentities;i++)
6271                 if (r_refdef.viewcache.entityvisible[i])
6272                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
6273
6274         if (r_shadows.integer)
6275                 for (i = 0;i < r_refdef.scene.numentities;i++)
6276                         if (!r_refdef.viewcache.entityvisible[i])
6277                                 R_AnimCache_GetEntity(r_refdef.scene.entities[i], false, false);
6278 }
6279
6280 //==================================================================================
6281
6282 static void R_View_UpdateEntityLighting (void)
6283 {
6284         int i;
6285         entity_render_t *ent;
6286         vec3_t tempdiffusenormal, avg;
6287         vec_t f, fa, fd, fdd;
6288
6289         for (i = 0;i < r_refdef.scene.numentities;i++)
6290         {
6291                 ent = r_refdef.scene.entities[i];
6292
6293                 // skip unseen models
6294                 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
6295                         continue;
6296
6297                 // skip bsp models
6298                 if (ent->model && ent->model->brush.num_leafs)
6299                 {
6300                         // TODO: use modellight for r_ambient settings on world?
6301                         VectorSet(ent->modellight_ambient, 0, 0, 0);
6302                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
6303                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
6304                         continue;
6305                 }
6306
6307                 // fetch the lighting from the worldmodel data
6308                 VectorClear(ent->modellight_ambient);
6309                 VectorClear(ent->modellight_diffuse);
6310                 VectorClear(tempdiffusenormal);
6311                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
6312                 {
6313                         vec3_t org;
6314                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6315                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
6316                         if(ent->flags & RENDER_EQUALIZE)
6317                         {
6318                                 // first fix up ambient lighting...
6319                                 if(r_equalize_entities_minambient.value > 0)
6320                                 {
6321                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
6322                                         if(fd > 0)
6323                                         {
6324                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
6325                                                 if(fa < r_equalize_entities_minambient.value * fd)
6326                                                 {
6327                                                         // solve:
6328                                                         //   fa'/fd' = minambient
6329                                                         //   fa'+0.25*fd' = fa+0.25*fd
6330                                                         //   ...
6331                                                         //   fa' = fd' * minambient
6332                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
6333                                                         //   ...
6334                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
6335                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
6336                                                         //   ...
6337                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
6338                                                         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
6339                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
6340                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6341                                                 }
6342                                         }
6343                                 }
6344
6345                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
6346                                 {
6347                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
6348                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
6349                                         if(f > 0)
6350                                         {
6351                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
6352                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
6353                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6354                                         }
6355                                 }
6356                         }
6357                 }
6358                 else // highly rare
6359                         VectorSet(ent->modellight_ambient, 1, 1, 1);
6360
6361                 // move the light direction into modelspace coordinates for lighting code
6362                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
6363                 if(VectorLength2(ent->modellight_lightdir) == 0)
6364                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
6365                 VectorNormalize(ent->modellight_lightdir);
6366         }
6367 }
6368
6369 #define MAX_LINEOFSIGHTTRACES 64
6370
6371 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
6372 {
6373         int i;
6374         vec3_t boxmins, boxmaxs;
6375         vec3_t start;
6376         vec3_t end;
6377         dp_model_t *model = r_refdef.scene.worldmodel;
6378
6379         if (!model || !model->brush.TraceLineOfSight)
6380                 return true;
6381
6382         // expand the box a little
6383         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
6384         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
6385         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
6386         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
6387         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
6388         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
6389
6390         // try center
6391         VectorCopy(eye, start);
6392         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
6393         if (model->brush.TraceLineOfSight(model, start, end))
6394                 return true;
6395
6396         // try various random positions
6397         for (i = 0;i < numsamples;i++)
6398         {
6399                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
6400                 if (model->brush.TraceLineOfSight(model, start, end))
6401                         return true;
6402         }
6403
6404         return false;
6405 }
6406
6407
6408 static void R_View_UpdateEntityVisible (void)
6409 {
6410         int i;
6411         int renderimask;
6412         int samples;
6413         entity_render_t *ent;
6414
6415         renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
6416         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
6417         {
6418                 // worldmodel can check visibility
6419                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
6420                 for (i = 0;i < r_refdef.scene.numentities;i++)
6421                 {
6422                         ent = r_refdef.scene.entities[i];
6423                         if (!(ent->flags & renderimask))
6424                         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)))
6425                         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))
6426                                 r_refdef.viewcache.entityvisible[i] = true;
6427                 }
6428                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
6429                 {
6430                         for (i = 0;i < r_refdef.scene.numentities;i++)
6431                         {
6432                                 ent = r_refdef.scene.entities[i];
6433                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
6434                                 {
6435                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
6436                                         if (samples < 0)
6437                                                 continue; // temp entities do pvs only
6438                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
6439                                                 ent->last_trace_visibility = realtime;
6440                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
6441                                                 r_refdef.viewcache.entityvisible[i] = 0;
6442                                 }
6443                         }
6444                 }
6445         }
6446         else
6447         {
6448                 // no worldmodel or it can't check visibility
6449                 for (i = 0;i < r_refdef.scene.numentities;i++)
6450                 {
6451                         ent = r_refdef.scene.entities[i];
6452                         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));
6453                 }
6454         }
6455 }
6456
6457 /// only used if skyrendermasked, and normally returns false
6458 int R_DrawBrushModelsSky (void)
6459 {
6460         int i, sky;
6461         entity_render_t *ent;
6462
6463         sky = false;
6464         for (i = 0;i < r_refdef.scene.numentities;i++)
6465         {
6466                 if (!r_refdef.viewcache.entityvisible[i])
6467                         continue;
6468                 ent = r_refdef.scene.entities[i];
6469                 if (!ent->model || !ent->model->DrawSky)
6470                         continue;
6471                 ent->model->DrawSky(ent);
6472                 sky = true;
6473         }
6474         return sky;
6475 }
6476
6477 static void R_DrawNoModel(entity_render_t *ent);
6478 static void R_DrawModels(void)
6479 {
6480         int i;
6481         entity_render_t *ent;
6482
6483         for (i = 0;i < r_refdef.scene.numentities;i++)
6484         {
6485                 if (!r_refdef.viewcache.entityvisible[i])
6486                         continue;
6487                 ent = r_refdef.scene.entities[i];
6488                 r_refdef.stats.entities++;
6489                 if (ent->model && ent->model->Draw != NULL)
6490                         ent->model->Draw(ent);
6491                 else
6492                         R_DrawNoModel(ent);
6493         }
6494 }
6495
6496 static void R_DrawModelsDepth(void)
6497 {
6498         int i;
6499         entity_render_t *ent;
6500
6501         for (i = 0;i < r_refdef.scene.numentities;i++)
6502         {
6503                 if (!r_refdef.viewcache.entityvisible[i])
6504                         continue;
6505                 ent = r_refdef.scene.entities[i];
6506                 if (ent->model && ent->model->DrawDepth != NULL)
6507                         ent->model->DrawDepth(ent);
6508         }
6509 }
6510
6511 static void R_DrawModelsDebug(void)
6512 {
6513         int i;
6514         entity_render_t *ent;
6515
6516         for (i = 0;i < r_refdef.scene.numentities;i++)
6517         {
6518                 if (!r_refdef.viewcache.entityvisible[i])
6519                         continue;
6520                 ent = r_refdef.scene.entities[i];
6521                 if (ent->model && ent->model->DrawDebug != NULL)
6522                         ent->model->DrawDebug(ent);
6523         }
6524 }
6525
6526 static void R_DrawModelsAddWaterPlanes(void)
6527 {
6528         int i;
6529         entity_render_t *ent;
6530
6531         for (i = 0;i < r_refdef.scene.numentities;i++)
6532         {
6533                 if (!r_refdef.viewcache.entityvisible[i])
6534                         continue;
6535                 ent = r_refdef.scene.entities[i];
6536                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
6537                         ent->model->DrawAddWaterPlanes(ent);
6538         }
6539 }
6540
6541 static void R_View_SetFrustum(void)
6542 {
6543         int i;
6544         double slopex, slopey;
6545         vec3_t forward, left, up, origin;
6546
6547         // we can't trust r_refdef.view.forward and friends in reflected scenes
6548         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
6549
6550 #if 0
6551         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
6552         r_refdef.view.frustum[0].normal[1] = 0 - 0;
6553         r_refdef.view.frustum[0].normal[2] = -1 - 0;
6554         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
6555         r_refdef.view.frustum[1].normal[1] = 0 + 0;
6556         r_refdef.view.frustum[1].normal[2] = -1 + 0;
6557         r_refdef.view.frustum[2].normal[0] = 0 - 0;
6558         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
6559         r_refdef.view.frustum[2].normal[2] = -1 - 0;
6560         r_refdef.view.frustum[3].normal[0] = 0 + 0;
6561         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
6562         r_refdef.view.frustum[3].normal[2] = -1 + 0;
6563 #endif
6564
6565 #if 0
6566         zNear = r_refdef.nearclip;
6567         nudge = 1.0 - 1.0 / (1<<23);
6568         r_refdef.view.frustum[4].normal[0] = 0 - 0;
6569         r_refdef.view.frustum[4].normal[1] = 0 - 0;
6570         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
6571         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
6572         r_refdef.view.frustum[5].normal[0] = 0 + 0;
6573         r_refdef.view.frustum[5].normal[1] = 0 + 0;
6574         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
6575         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
6576 #endif
6577
6578
6579
6580 #if 0
6581         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
6582         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
6583         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
6584         r_refdef.view.frustum[0].dist = m[15] - m[12];
6585
6586         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
6587         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
6588         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
6589         r_refdef.view.frustum[1].dist = m[15] + m[12];
6590
6591         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
6592         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
6593         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
6594         r_refdef.view.frustum[2].dist = m[15] - m[13];
6595
6596         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
6597         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
6598         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
6599         r_refdef.view.frustum[3].dist = m[15] + m[13];
6600
6601         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
6602         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
6603         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
6604         r_refdef.view.frustum[4].dist = m[15] - m[14];
6605
6606         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
6607         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
6608         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
6609         r_refdef.view.frustum[5].dist = m[15] + m[14];
6610 #endif
6611
6612         if (r_refdef.view.useperspective)
6613         {
6614                 slopex = 1.0 / r_refdef.view.frustum_x;
6615                 slopey = 1.0 / r_refdef.view.frustum_y;
6616                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
6617                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
6618                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
6619                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
6620                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6621
6622                 // Leaving those out was a mistake, those were in the old code, and they
6623                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
6624                 // I couldn't reproduce it after adding those normalizations. --blub
6625                 VectorNormalize(r_refdef.view.frustum[0].normal);
6626                 VectorNormalize(r_refdef.view.frustum[1].normal);
6627                 VectorNormalize(r_refdef.view.frustum[2].normal);
6628                 VectorNormalize(r_refdef.view.frustum[3].normal);
6629
6630                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
6631                 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]);
6632                 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]);
6633                 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]);
6634                 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]);
6635
6636                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
6637                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
6638                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
6639                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
6640                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6641         }
6642         else
6643         {
6644                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
6645                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
6646                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
6647                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
6648                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6649                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
6650                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
6651                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
6652                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
6653                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6654         }
6655         r_refdef.view.numfrustumplanes = 5;
6656
6657         if (r_refdef.view.useclipplane)
6658         {
6659                 r_refdef.view.numfrustumplanes = 6;
6660                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
6661         }
6662
6663         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6664                 PlaneClassify(r_refdef.view.frustum + i);
6665
6666         // LordHavoc: note to all quake engine coders, Quake had a special case
6667         // for 90 degrees which assumed a square view (wrong), so I removed it,
6668         // Quake2 has it disabled as well.
6669
6670         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
6671         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
6672         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
6673         //PlaneClassify(&frustum[0]);
6674
6675         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
6676         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
6677         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
6678         //PlaneClassify(&frustum[1]);
6679
6680         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
6681         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
6682         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
6683         //PlaneClassify(&frustum[2]);
6684
6685         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
6686         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
6687         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
6688         //PlaneClassify(&frustum[3]);
6689
6690         // nearclip plane
6691         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
6692         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
6693         //PlaneClassify(&frustum[4]);
6694 }
6695
6696 void R_View_Update(void)
6697 {
6698         R_Main_ResizeViewCache();
6699         R_View_SetFrustum();
6700         R_View_WorldVisibility(r_refdef.view.useclipplane);
6701         R_View_UpdateEntityVisible();
6702         R_View_UpdateEntityLighting();
6703 }
6704
6705 void R_SetupView(qboolean allowwaterclippingplane)
6706 {
6707         const float *customclipplane = NULL;
6708         float plane[4];
6709         if (r_refdef.view.useclipplane && allowwaterclippingplane)
6710         {
6711                 // LordHavoc: couldn't figure out how to make this approach the
6712                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
6713                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
6714                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
6715                         dist = r_refdef.view.clipplane.dist;
6716                 plane[0] = r_refdef.view.clipplane.normal[0];
6717                 plane[1] = r_refdef.view.clipplane.normal[1];
6718                 plane[2] = r_refdef.view.clipplane.normal[2];
6719                 plane[3] = dist;
6720                 customclipplane = plane;
6721         }
6722
6723         if (!r_refdef.view.useperspective)
6724                 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);
6725         else if (vid.stencil && r_useinfinitefarclip.integer)
6726                 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);
6727         else
6728                 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);
6729         R_SetViewport(&r_refdef.view.viewport);
6730 }
6731
6732 void R_EntityMatrix(const matrix4x4_t *matrix)
6733 {
6734         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
6735         {
6736                 gl_modelmatrixchanged = false;
6737                 gl_modelmatrix = *matrix;
6738                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
6739                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
6740                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
6741                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
6742                 CHECKGLERROR
6743                 switch(vid.renderpath)
6744                 {
6745                 case RENDERPATH_GL20:
6746                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
6747                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
6748                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6749                         break;
6750                 case RENDERPATH_CGGL:
6751 #ifdef SUPPORTCG
6752                         CHECKCGERROR
6753                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
6754                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
6755                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6756 #endif
6757                         break;
6758                 case RENDERPATH_GL13:
6759                 case RENDERPATH_GL11:
6760                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6761                         break;
6762                 }
6763         }
6764 }
6765
6766 void R_ResetViewRendering2D(void)
6767 {
6768         r_viewport_t viewport;
6769         DrawQ_Finish();
6770
6771         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
6772         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);
6773         R_SetViewport(&viewport);
6774         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
6775         GL_Color(1, 1, 1, 1);
6776         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6777         GL_BlendFunc(GL_ONE, GL_ZERO);
6778         GL_AlphaTest(false);
6779         GL_ScissorTest(false);
6780         GL_DepthMask(false);
6781         GL_DepthRange(0, 1);
6782         GL_DepthTest(false);
6783         R_EntityMatrix(&identitymatrix);
6784         R_Mesh_ResetTextureState();
6785         GL_PolygonOffset(0, 0);
6786         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
6787         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6788         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
6789         qglStencilMask(~0);CHECKGLERROR
6790         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
6791         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
6792         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
6793 }
6794
6795 void R_ResetViewRendering3D(void)
6796 {
6797         DrawQ_Finish();
6798
6799         R_SetupView(true);
6800         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6801         GL_Color(1, 1, 1, 1);
6802         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6803         GL_BlendFunc(GL_ONE, GL_ZERO);
6804         GL_AlphaTest(false);
6805         GL_ScissorTest(true);
6806         GL_DepthMask(true);
6807         GL_DepthRange(0, 1);
6808         GL_DepthTest(true);
6809         R_EntityMatrix(&identitymatrix);
6810         R_Mesh_ResetTextureState();
6811         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6812         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
6813         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6814         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
6815         qglStencilMask(~0);CHECKGLERROR
6816         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
6817         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
6818         GL_CullFace(r_refdef.view.cullface_back);
6819 }
6820
6821 void R_RenderScene(void);
6822 void R_RenderWaterPlanes(void);
6823
6824 static void R_Water_StartFrame(void)
6825 {
6826         int i;
6827         int waterwidth, waterheight, texturewidth, textureheight;
6828         r_waterstate_waterplane_t *p;
6829
6830         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
6831                 return;
6832
6833         switch(vid.renderpath)
6834         {
6835         case RENDERPATH_GL20:
6836         case RENDERPATH_CGGL:
6837                 break;
6838         case RENDERPATH_GL13:
6839         case RENDERPATH_GL11:
6840                 return;
6841         }
6842
6843         // set waterwidth and waterheight to the water resolution that will be
6844         // used (often less than the screen resolution for faster rendering)
6845         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
6846         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
6847
6848         // calculate desired texture sizes
6849         // can't use water if the card does not support the texture size
6850         if (!r_water.integer || r_showsurfaces.integer)
6851                 texturewidth = textureheight = waterwidth = waterheight = 0;
6852         else if (vid.support.arb_texture_non_power_of_two)
6853         {
6854                 texturewidth = waterwidth;
6855                 textureheight = waterheight;
6856         }
6857         else
6858         {
6859                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
6860                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
6861         }
6862
6863         // allocate textures as needed
6864         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
6865         {
6866                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
6867                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
6868                 {
6869                         if (p->texture_refraction)
6870                                 R_FreeTexture(p->texture_refraction);
6871                         p->texture_refraction = NULL;
6872                         if (p->texture_reflection)
6873                                 R_FreeTexture(p->texture_reflection);
6874                         p->texture_reflection = NULL;
6875                 }
6876                 memset(&r_waterstate, 0, sizeof(r_waterstate));
6877                 r_waterstate.texturewidth = texturewidth;
6878                 r_waterstate.textureheight = textureheight;
6879         }
6880
6881         if (r_waterstate.texturewidth)
6882         {
6883                 r_waterstate.enabled = true;
6884
6885                 // when doing a reduced render (HDR) we want to use a smaller area
6886                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
6887                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
6888
6889                 // set up variables that will be used in shader setup
6890                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
6891                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
6892                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
6893                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
6894         }
6895
6896         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
6897         r_waterstate.numwaterplanes = 0;
6898 }
6899
6900 void R_Water_AddWaterPlane(msurface_t *surface)
6901 {
6902         int triangleindex, planeindex;
6903         const int *e;
6904         vec3_t vert[3];
6905         vec3_t normal;
6906         vec3_t center;
6907         mplane_t plane;
6908         r_waterstate_waterplane_t *p;
6909         texture_t *t = R_GetCurrentTexture(surface->texture);
6910         // just use the first triangle with a valid normal for any decisions
6911         VectorClear(normal);
6912         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
6913         {
6914                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
6915                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
6916                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
6917                 TriangleNormal(vert[0], vert[1], vert[2], normal);
6918                 if (VectorLength2(normal) >= 0.001)
6919                         break;
6920         }
6921
6922         VectorCopy(normal, plane.normal);
6923         VectorNormalize(plane.normal);
6924         plane.dist = DotProduct(vert[0], plane.normal);
6925         PlaneClassify(&plane);
6926         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
6927         {
6928                 // skip backfaces (except if nocullface is set)
6929                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
6930                         return;
6931                 VectorNegate(plane.normal, plane.normal);
6932                 plane.dist *= -1;
6933                 PlaneClassify(&plane);
6934         }
6935
6936
6937         // find a matching plane if there is one
6938         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6939                 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
6940                         break;
6941         if (planeindex >= r_waterstate.maxwaterplanes)
6942                 return; // nothing we can do, out of planes
6943
6944         // if this triangle does not fit any known plane rendered this frame, add one
6945         if (planeindex >= r_waterstate.numwaterplanes)
6946         {
6947                 // store the new plane
6948                 r_waterstate.numwaterplanes++;
6949                 p->plane = plane;
6950                 // clear materialflags and pvs
6951                 p->materialflags = 0;
6952                 p->pvsvalid = false;
6953         }
6954         // merge this surface's materialflags into the waterplane
6955         p->materialflags |= t->currentmaterialflags;
6956         // merge this surface's PVS into the waterplane
6957         VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
6958         if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6959          && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6960         {
6961                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6962                 p->pvsvalid = true;
6963         }
6964 }
6965
6966 static void R_Water_ProcessPlanes(void)
6967 {
6968         r_refdef_view_t originalview;
6969         r_refdef_view_t myview;
6970         int planeindex;
6971         r_waterstate_waterplane_t *p;
6972
6973         originalview = r_refdef.view;
6974
6975         // make sure enough textures are allocated
6976         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6977         {
6978                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6979                 {
6980                         if (!p->texture_refraction)
6981                                 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);
6982                         if (!p->texture_refraction)
6983                                 goto error;
6984                 }
6985
6986                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6987                 {
6988                         if (!p->texture_reflection)
6989                                 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);
6990                         if (!p->texture_reflection)
6991                                 goto error;
6992                 }
6993         }
6994
6995         // render views
6996         r_refdef.view = originalview;
6997         r_refdef.view.showdebug = false;
6998         r_refdef.view.width = r_waterstate.waterwidth;
6999         r_refdef.view.height = r_waterstate.waterheight;
7000         r_refdef.view.useclipplane = true;
7001         myview = r_refdef.view;
7002         r_waterstate.renderingscene = true;
7003         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7004         {
7005                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7006                 {
7007                         r_refdef.view = myview;
7008                         // render reflected scene and copy into texture
7009                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
7010                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
7011                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
7012                         r_refdef.view.clipplane = p->plane;
7013                         // reverse the cullface settings for this render
7014                         r_refdef.view.cullface_front = GL_FRONT;
7015                         r_refdef.view.cullface_back = GL_BACK;
7016                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
7017                         {
7018                                 r_refdef.view.usecustompvs = true;
7019                                 if (p->pvsvalid)
7020                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7021                                 else
7022                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7023                         }
7024
7025                         R_ResetViewRendering3D();
7026                         R_ClearScreen(r_refdef.fogenabled);
7027                         R_View_Update();
7028                         R_RenderScene();
7029
7030                         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);
7031                 }
7032
7033                 // render the normal view scene and copy into texture
7034                 // (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)
7035                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7036                 {
7037                         r_refdef.view = myview;
7038                         r_refdef.view.clipplane = p->plane;
7039                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
7040                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
7041                         PlaneClassify(&r_refdef.view.clipplane);
7042
7043                         R_ResetViewRendering3D();
7044                         R_ClearScreen(r_refdef.fogenabled);
7045                         R_View_Update();
7046                         R_RenderScene();
7047
7048                         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);
7049                 }
7050
7051         }
7052         r_waterstate.renderingscene = false;
7053         r_refdef.view = originalview;
7054         R_ResetViewRendering3D();
7055         R_ClearScreen(r_refdef.fogenabled);
7056         R_View_Update();
7057         return;
7058 error:
7059         r_refdef.view = originalview;
7060         r_waterstate.renderingscene = false;
7061         Cvar_SetValueQuick(&r_water, 0);
7062         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
7063         return;
7064 }
7065
7066 void R_Bloom_StartFrame(void)
7067 {
7068         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
7069
7070         switch(vid.renderpath)
7071         {
7072         case RENDERPATH_GL20:
7073         case RENDERPATH_CGGL:
7074                 break;
7075         case RENDERPATH_GL13:
7076         case RENDERPATH_GL11:
7077                 return;
7078         }
7079
7080         // set bloomwidth and bloomheight to the bloom resolution that will be
7081         // used (often less than the screen resolution for faster rendering)
7082         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
7083         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
7084         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
7085         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
7086         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
7087
7088         // calculate desired texture sizes
7089         if (vid.support.arb_texture_non_power_of_two)
7090         {
7091                 screentexturewidth = r_refdef.view.width;
7092                 screentextureheight = r_refdef.view.height;
7093                 bloomtexturewidth = r_bloomstate.bloomwidth;
7094                 bloomtextureheight = r_bloomstate.bloomheight;
7095         }
7096         else
7097         {
7098                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
7099                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
7100                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
7101                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
7102         }
7103
7104         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))
7105         {
7106                 Cvar_SetValueQuick(&r_hdr, 0);
7107                 Cvar_SetValueQuick(&r_bloom, 0);
7108                 Cvar_SetValueQuick(&r_motionblur, 0);
7109                 Cvar_SetValueQuick(&r_damageblur, 0);
7110         }
7111
7112         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)))
7113                 screentexturewidth = screentextureheight = 0;
7114         if (!r_hdr.integer && !r_bloom.integer)
7115                 bloomtexturewidth = bloomtextureheight = 0;
7116
7117         // allocate textures as needed
7118         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
7119         {
7120                 if (r_bloomstate.texture_screen)
7121                         R_FreeTexture(r_bloomstate.texture_screen);
7122                 r_bloomstate.texture_screen = NULL;
7123                 r_bloomstate.screentexturewidth = screentexturewidth;
7124                 r_bloomstate.screentextureheight = screentextureheight;
7125                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
7126                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
7127         }
7128         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
7129         {
7130                 if (r_bloomstate.texture_bloom)
7131                         R_FreeTexture(r_bloomstate.texture_bloom);
7132                 r_bloomstate.texture_bloom = NULL;
7133                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
7134                 r_bloomstate.bloomtextureheight = bloomtextureheight;
7135                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
7136                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7137         }
7138
7139         // when doing a reduced render (HDR) we want to use a smaller area
7140         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
7141         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
7142         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
7143         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
7144         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
7145
7146         // set up a texcoord array for the full resolution screen image
7147         // (we have to keep this around to copy back during final render)
7148         r_bloomstate.screentexcoord2f[0] = 0;
7149         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7150         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7151         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7152         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7153         r_bloomstate.screentexcoord2f[5] = 0;
7154         r_bloomstate.screentexcoord2f[6] = 0;
7155         r_bloomstate.screentexcoord2f[7] = 0;
7156
7157         // set up a texcoord array for the reduced resolution bloom image
7158         // (which will be additive blended over the screen image)
7159         r_bloomstate.bloomtexcoord2f[0] = 0;
7160         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7161         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7162         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7163         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7164         r_bloomstate.bloomtexcoord2f[5] = 0;
7165         r_bloomstate.bloomtexcoord2f[6] = 0;
7166         r_bloomstate.bloomtexcoord2f[7] = 0;
7167
7168         if (r_hdr.integer || r_bloom.integer)
7169         {
7170                 r_bloomstate.enabled = true;
7171                 r_bloomstate.hdr = r_hdr.integer != 0;
7172         }
7173
7174         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);
7175 }
7176
7177 void R_Bloom_CopyBloomTexture(float colorscale)
7178 {
7179         r_refdef.stats.bloom++;
7180
7181         // scale down screen texture to the bloom texture size
7182         CHECKGLERROR
7183         R_SetViewport(&r_bloomstate.viewport);
7184         GL_BlendFunc(GL_ONE, GL_ZERO);
7185         GL_Color(colorscale, colorscale, colorscale, 1);
7186         // TODO: optimize with multitexture or GLSL
7187         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7188         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7189         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7190         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7191
7192         // we now have a bloom image in the framebuffer
7193         // copy it into the bloom image texture for later processing
7194         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);
7195         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7196 }
7197
7198 void R_Bloom_CopyHDRTexture(void)
7199 {
7200         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);
7201         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7202 }
7203
7204 void R_Bloom_MakeTexture(void)
7205 {
7206         int x, range, dir;
7207         float xoffset, yoffset, r, brighten;
7208
7209         r_refdef.stats.bloom++;
7210
7211         R_ResetViewRendering2D();
7212         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7213         R_Mesh_ColorPointer(NULL, 0, 0);
7214
7215         // we have a bloom image in the framebuffer
7216         CHECKGLERROR
7217         R_SetViewport(&r_bloomstate.viewport);
7218
7219         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
7220         {
7221                 x *= 2;
7222                 r = bound(0, r_bloom_colorexponent.value / x, 1);
7223                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7224                 GL_Color(r, r, r, 1);
7225                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7226                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7227                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7228                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7229
7230                 // copy the vertically blurred bloom view to a texture
7231                 GL_ActiveTexture(0);
7232                 CHECKGLERROR
7233                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
7234                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7235         }
7236
7237         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
7238         brighten = r_bloom_brighten.value;
7239         if (r_hdr.integer)
7240                 brighten *= r_hdr_range.value;
7241         brighten = sqrt(brighten);
7242         if(range >= 1)
7243                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
7244         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7245         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
7246
7247         for (dir = 0;dir < 2;dir++)
7248         {
7249                 // blend on at multiple vertical offsets to achieve a vertical blur
7250                 // TODO: do offset blends using GLSL
7251                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
7252                 GL_BlendFunc(GL_ONE, GL_ZERO);
7253                 for (x = -range;x <= range;x++)
7254                 {
7255                         if (!dir){xoffset = 0;yoffset = x;}
7256                         else {xoffset = x;yoffset = 0;}
7257                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
7258                         yoffset /= (float)r_bloomstate.bloomtextureheight;
7259                         // compute a texcoord array with the specified x and y offset
7260                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
7261                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7262                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7263                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7264                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7265                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
7266                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
7267                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
7268                         // this r value looks like a 'dot' particle, fading sharply to
7269                         // black at the edges
7270                         // (probably not realistic but looks good enough)
7271                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
7272                         //r = brighten/(range*2+1);
7273                         r = brighten / (range * 2 + 1);
7274                         if(range >= 1)
7275                                 r *= (1 - x*x/(float)(range*range));
7276                         GL_Color(r, r, r, 1);
7277                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7278                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7279                         GL_BlendFunc(GL_ONE, GL_ONE);
7280                 }
7281
7282                 // copy the vertically blurred bloom view to a texture
7283                 GL_ActiveTexture(0);
7284                 CHECKGLERROR
7285                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
7286                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7287         }
7288
7289         // apply subtract last
7290         // (just like it would be in a GLSL shader)
7291         if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
7292         {
7293                 GL_BlendFunc(GL_ONE, GL_ZERO);
7294                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7295                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7296                 GL_Color(1, 1, 1, 1);
7297                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7298                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7299
7300                 GL_BlendFunc(GL_ONE, GL_ONE);
7301                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
7302                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7303                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7304                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
7305                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7306                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7307                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
7308
7309                 // copy the darkened bloom view to a texture
7310                 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);
7311                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7312         }
7313 }
7314
7315 void R_HDR_RenderBloomTexture(void)
7316 {
7317         int oldwidth, oldheight;
7318         float oldcolorscale;
7319
7320         oldcolorscale = r_refdef.view.colorscale;
7321         oldwidth = r_refdef.view.width;
7322         oldheight = r_refdef.view.height;
7323         r_refdef.view.width = r_bloomstate.bloomwidth;
7324         r_refdef.view.height = r_bloomstate.bloomheight;
7325
7326         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
7327         // TODO: add exposure compensation features
7328         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
7329
7330         r_refdef.view.showdebug = false;
7331         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
7332
7333         R_ResetViewRendering3D();
7334
7335         R_ClearScreen(r_refdef.fogenabled);
7336         if (r_timereport_active)
7337                 R_TimeReport("HDRclear");
7338
7339         R_View_Update();
7340         if (r_timereport_active)
7341                 R_TimeReport("visibility");
7342
7343         // only do secondary renders with HDR if r_hdr is 2 or higher
7344         r_waterstate.numwaterplanes = 0;
7345         if (r_waterstate.enabled && r_hdr.integer >= 2)
7346                 R_RenderWaterPlanes();
7347
7348         r_refdef.view.showdebug = true;
7349         R_RenderScene();
7350         r_waterstate.numwaterplanes = 0;
7351
7352         R_ResetViewRendering2D();
7353
7354         R_Bloom_CopyHDRTexture();
7355         R_Bloom_MakeTexture();
7356
7357         // restore the view settings
7358         r_refdef.view.width = oldwidth;
7359         r_refdef.view.height = oldheight;
7360         r_refdef.view.colorscale = oldcolorscale;
7361
7362         R_ResetViewRendering3D();
7363
7364         R_ClearScreen(r_refdef.fogenabled);
7365         if (r_timereport_active)
7366                 R_TimeReport("viewclear");
7367 }
7368
7369 static void R_BlendView(void)
7370 {
7371         unsigned int permutation;
7372         float uservecs[4][4];
7373
7374         switch (vid.renderpath)
7375         {
7376         case RENDERPATH_GL20:
7377         case RENDERPATH_CGGL:
7378                 permutation =
7379                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
7380                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
7381                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
7382                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
7383                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
7384
7385                 if (r_bloomstate.texture_screen)
7386                 {
7387                         // make sure the buffer is available
7388                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
7389
7390                         R_ResetViewRendering2D();
7391                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7392                         R_Mesh_ColorPointer(NULL, 0, 0);
7393
7394                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
7395                         {
7396                                 // declare variables
7397                                 float speed;
7398                                 static float avgspeed;
7399
7400                                 speed = VectorLength(cl.movement_velocity);
7401
7402                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
7403                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
7404
7405                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
7406                                 speed = bound(0, speed, 1);
7407                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
7408
7409                                 // calculate values into a standard alpha
7410                                 cl.motionbluralpha = 1 - exp(-
7411                                                 (
7412                                                  (r_motionblur.value * speed / 80)
7413                                                  +
7414                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
7415                                                 )
7416                                                 /
7417                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
7418                                            );
7419
7420                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
7421                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
7422                                 // apply the blur
7423                                 if (cl.motionbluralpha > 0)
7424                                 {
7425                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7426                                         GL_Color(1, 1, 1, cl.motionbluralpha);
7427                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7428                                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7429                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7430                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7431                                 }
7432                         }
7433
7434                         // copy view into the screen texture
7435                         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);
7436                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7437                 }
7438                 else if (!r_bloomstate.texture_bloom)
7439                 {
7440                         // we may still have to do view tint...
7441                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7442                         {
7443                                 // apply a color tint to the whole view
7444                                 R_ResetViewRendering2D();
7445                                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7446                                 R_Mesh_ColorPointer(NULL, 0, 0);
7447                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7448                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7449                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7450                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7451                         }
7452                         break; // no screen processing, no bloom, skip it
7453                 }
7454
7455                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
7456                 {
7457                         // render simple bloom effect
7458                         // copy the screen and shrink it and darken it for the bloom process
7459                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
7460                         // make the bloom texture
7461                         R_Bloom_MakeTexture();
7462                 }
7463
7464 #if _MSC_VER >= 1400
7465 #define sscanf sscanf_s
7466 #endif
7467                 memset(uservecs, 0, sizeof(uservecs));
7468                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
7469                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
7470                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
7471                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
7472
7473                 R_ResetViewRendering2D();
7474                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7475                 R_Mesh_ColorPointer(NULL, 0, 0);
7476                 GL_Color(1, 1, 1, 1);
7477                 GL_BlendFunc(GL_ONE, GL_ZERO);
7478                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7479                 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7480
7481                 switch(vid.renderpath)
7482                 {
7483                 case RENDERPATH_GL20:
7484                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
7485                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
7486                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
7487                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
7488                         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]);
7489                         if (r_glsl_permutation->loc_ClientTime         >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime        , cl.time);
7490                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
7491                         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]);
7492                         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]);
7493                         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]);
7494                         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]);
7495                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
7496                         break;
7497                 case RENDERPATH_CGGL:
7498 #ifdef SUPPORTCG
7499                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
7500                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
7501                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
7502                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
7503                         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
7504                         if (r_cg_permutation->fp_ClientTime        ) cgGLSetParameter1f(     r_cg_permutation->fp_ClientTime        , cl.time);CHECKCGERROR
7505                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
7506                         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
7507                         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
7508                         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
7509                         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
7510                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
7511 #endif
7512                         break;
7513                 default:
7514                         break;
7515                 }
7516                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7517                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7518                 break;
7519         case RENDERPATH_GL13:
7520         case RENDERPATH_GL11:
7521                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7522                 {
7523                         // apply a color tint to the whole view
7524                         R_ResetViewRendering2D();
7525                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7526                         R_Mesh_ColorPointer(NULL, 0, 0);
7527                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7528                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7529                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7530                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7531                 }
7532                 break;
7533         }
7534 }
7535
7536 matrix4x4_t r_waterscrollmatrix;
7537
7538 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
7539 {
7540         if (r_refdef.fog_density)
7541         {
7542                 r_refdef.fogcolor[0] = r_refdef.fog_red;
7543                 r_refdef.fogcolor[1] = r_refdef.fog_green;
7544                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7545
7546                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7547                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7548                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7549                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7550
7551                 {
7552                         vec3_t fogvec;
7553                         VectorCopy(r_refdef.fogcolor, fogvec);
7554                         //   color.rgb *= ContrastBoost * SceneBrightness;
7555                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7556                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7557                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7558                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7559                 }
7560         }
7561 }
7562
7563 void R_UpdateVariables(void)
7564 {
7565         R_Textures_Frame();
7566
7567         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7568
7569         r_refdef.farclip = r_farclip_base.value;
7570         if (r_refdef.scene.worldmodel)
7571                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7572         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7573
7574         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7575                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7576         r_refdef.polygonfactor = 0;
7577         r_refdef.polygonoffset = 0;
7578         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7579         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7580
7581         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7582         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7583         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
7584         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7585         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7586         if (r_showsurfaces.integer)
7587         {
7588                 r_refdef.scene.rtworld = false;
7589                 r_refdef.scene.rtworldshadows = false;
7590                 r_refdef.scene.rtdlight = false;
7591                 r_refdef.scene.rtdlightshadows = false;
7592                 r_refdef.lightmapintensity = 0;
7593         }
7594
7595         if (gamemode == GAME_NEHAHRA)
7596         {
7597                 if (gl_fogenable.integer)
7598                 {
7599                         r_refdef.oldgl_fogenable = true;
7600                         r_refdef.fog_density = gl_fogdensity.value;
7601                         r_refdef.fog_red = gl_fogred.value;
7602                         r_refdef.fog_green = gl_foggreen.value;
7603                         r_refdef.fog_blue = gl_fogblue.value;
7604                         r_refdef.fog_alpha = 1;
7605                         r_refdef.fog_start = 0;
7606                         r_refdef.fog_end = gl_skyclip.value;
7607                         r_refdef.fog_height = 1<<30;
7608                         r_refdef.fog_fadedepth = 128;
7609                 }
7610                 else if (r_refdef.oldgl_fogenable)
7611                 {
7612                         r_refdef.oldgl_fogenable = false;
7613                         r_refdef.fog_density = 0;
7614                         r_refdef.fog_red = 0;
7615                         r_refdef.fog_green = 0;
7616                         r_refdef.fog_blue = 0;
7617                         r_refdef.fog_alpha = 0;
7618                         r_refdef.fog_start = 0;
7619                         r_refdef.fog_end = 0;
7620                         r_refdef.fog_height = 1<<30;
7621                         r_refdef.fog_fadedepth = 128;
7622                 }
7623         }
7624
7625         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7626         r_refdef.fog_start = max(0, r_refdef.fog_start);
7627         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7628
7629         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
7630
7631         if (r_refdef.fog_density && r_drawfog.integer)
7632         {
7633                 r_refdef.fogenabled = true;
7634                 // this is the point where the fog reaches 0.9986 alpha, which we
7635                 // consider a good enough cutoff point for the texture
7636                 // (0.9986 * 256 == 255.6)
7637                 if (r_fog_exp2.integer)
7638                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7639                 else
7640                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7641                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7642                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7643                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7644                 // fog color was already set
7645                 // update the fog texture
7646                 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)
7647                         R_BuildFogTexture();
7648         }
7649         else
7650                 r_refdef.fogenabled = false;
7651
7652         switch(vid.renderpath)
7653         {
7654         case RENDERPATH_GL20:
7655         case RENDERPATH_CGGL:
7656                 if(v_glslgamma.integer && !vid_gammatables_trivial)
7657                 {
7658                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7659                         {
7660                                 // build GLSL gamma texture
7661 #define RAMPWIDTH 256
7662                                 unsigned short ramp[RAMPWIDTH * 3];
7663                                 unsigned char rampbgr[RAMPWIDTH][4];
7664                                 int i;
7665
7666                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7667
7668                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7669                                 for(i = 0; i < RAMPWIDTH; ++i)
7670                                 {
7671                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7672                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7673                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7674                                         rampbgr[i][3] = 0;
7675                                 }
7676                                 if (r_texture_gammaramps)
7677                                 {
7678                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
7679                                 }
7680                                 else
7681                                 {
7682                                         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);
7683                                 }
7684                         }
7685                 }
7686                 else
7687                 {
7688                         // remove GLSL gamma texture
7689                 }
7690                 break;
7691         case RENDERPATH_GL13:
7692         case RENDERPATH_GL11:
7693                 break;
7694         }
7695 }
7696
7697 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7698 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7699 /*
7700 ================
7701 R_SelectScene
7702 ================
7703 */
7704 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7705         if( scenetype != r_currentscenetype ) {
7706                 // store the old scenetype
7707                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7708                 r_currentscenetype = scenetype;
7709                 // move in the new scene
7710                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7711         }
7712 }
7713
7714 /*
7715 ================
7716 R_GetScenePointer
7717 ================
7718 */
7719 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7720 {
7721         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7722         if( scenetype == r_currentscenetype ) {
7723                 return &r_refdef.scene;
7724         } else {
7725                 return &r_scenes_store[ scenetype ];
7726         }
7727 }
7728
7729 /*
7730 ================
7731 R_RenderView
7732 ================
7733 */
7734 void R_RenderView(void)
7735 {
7736         if (r_timereport_active)
7737                 R_TimeReport("start");
7738         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7739
7740         if (!r_drawentities.integer)
7741                 r_refdef.scene.numentities = 0;
7742
7743         R_AnimCache_ClearCache();
7744         R_FrameData_NewFrame();
7745
7746         if (r_refdef.view.isoverlay)
7747         {
7748                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7749                 GL_Clear( GL_DEPTH_BUFFER_BIT );
7750                 R_TimeReport("depthclear");
7751
7752                 r_refdef.view.showdebug = false;
7753
7754                 r_waterstate.enabled = false;
7755                 r_waterstate.numwaterplanes = 0;
7756
7757                 R_RenderScene();
7758
7759                 CHECKGLERROR
7760                 return;
7761         }
7762
7763         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
7764                 return; //Host_Error ("R_RenderView: NULL worldmodel");
7765
7766         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
7767
7768         // break apart the view matrix into vectors for various purposes
7769         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
7770         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
7771         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
7772         VectorNegate(r_refdef.view.left, r_refdef.view.right);
7773         // make an inverted copy of the view matrix for tracking sprites
7774         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
7775
7776         R_Shadow_UpdateWorldLightSelection();
7777
7778         R_Bloom_StartFrame();
7779         R_Water_StartFrame();
7780
7781         CHECKGLERROR
7782         if (r_timereport_active)
7783                 R_TimeReport("viewsetup");
7784
7785         R_ResetViewRendering3D();
7786
7787         if (r_refdef.view.clear || r_refdef.fogenabled)
7788         {
7789                 R_ClearScreen(r_refdef.fogenabled);
7790                 if (r_timereport_active)
7791                         R_TimeReport("viewclear");
7792         }
7793         r_refdef.view.clear = true;
7794
7795         // this produces a bloom texture to be used in R_BlendView() later
7796         if (r_hdr.integer && r_bloomstate.bloomwidth)
7797                 R_HDR_RenderBloomTexture();
7798
7799         r_refdef.view.showdebug = true;
7800
7801         R_View_Update();
7802         if (r_timereport_active)
7803                 R_TimeReport("visibility");
7804
7805         r_waterstate.numwaterplanes = 0;
7806         if (r_waterstate.enabled)
7807                 R_RenderWaterPlanes();
7808
7809         R_RenderScene();
7810         r_waterstate.numwaterplanes = 0;
7811
7812         R_BlendView();
7813         if (r_timereport_active)
7814                 R_TimeReport("blendview");
7815
7816         GL_Scissor(0, 0, vid.width, vid.height);
7817         GL_ScissorTest(false);
7818         CHECKGLERROR
7819 }
7820
7821 void R_RenderWaterPlanes(void)
7822 {
7823         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7824         {
7825                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7826                 if (r_timereport_active)
7827                         R_TimeReport("waterworld");
7828         }
7829
7830         // don't let sound skip if going slow
7831         if (r_refdef.scene.extraupdate)
7832                 S_ExtraUpdate ();
7833
7834         R_DrawModelsAddWaterPlanes();
7835         if (r_timereport_active)
7836                 R_TimeReport("watermodels");
7837
7838         if (r_waterstate.numwaterplanes)
7839         {
7840                 R_Water_ProcessPlanes();
7841                 if (r_timereport_active)
7842                         R_TimeReport("waterscenes");
7843         }
7844 }
7845
7846 extern void R_DrawLightningBeams (void);
7847 extern void VM_CL_AddPolygonsToMeshQueue (void);
7848 extern void R_DrawPortals (void);
7849 extern cvar_t cl_locs_show;
7850 static void R_DrawLocs(void);
7851 static void R_DrawEntityBBoxes(void);
7852 static void R_DrawModelDecals(void);
7853 extern cvar_t cl_decals_newsystem;
7854 extern qboolean r_shadow_usingdeferredprepass;
7855 void R_RenderScene(void)
7856 {
7857         r_refdef.stats.renders++;
7858         r_textureframe++; // used only by R_GetCurrentTexture
7859
7860         R_UpdateFogColor();
7861
7862         // don't let sound skip if going slow
7863         if (r_refdef.scene.extraupdate)
7864                 S_ExtraUpdate ();
7865
7866         R_MeshQueue_BeginScene();
7867
7868         R_SkyStartFrame();
7869
7870         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);
7871
7872         if (cl.csqc_vidvars.drawworld)
7873         {
7874                 // don't let sound skip if going slow
7875                 if (r_refdef.scene.extraupdate)
7876                         S_ExtraUpdate ();
7877
7878                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7879                 {
7880                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7881                         if (r_timereport_active)
7882                                 R_TimeReport("worldsky");
7883                 }
7884
7885                 if (R_DrawBrushModelsSky() && r_timereport_active)
7886                         R_TimeReport("bmodelsky");
7887
7888                 if (skyrendermasked && skyrenderlater)
7889                 {
7890                         // we have to force off the water clipping plane while rendering sky
7891                         R_SetupView(false);
7892                         R_Sky();
7893                         R_SetupView(true);
7894                         if (r_timereport_active)
7895                                 R_TimeReport("sky");
7896                 }
7897         }
7898
7899         R_AnimCache_CacheVisibleEntities();
7900         if (r_timereport_active)
7901                 R_TimeReport("animation");
7902
7903         R_Shadow_PrepareLights();
7904         if (r_timereport_active)
7905                 R_TimeReport("preparelights");
7906
7907         if (r_shadow_usingdeferredprepass)
7908                 R_Shadow_DrawPrepass();
7909
7910         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7911         {
7912                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7913                 if (r_timereport_active)
7914                         R_TimeReport("worlddepth");
7915         }
7916         if (r_depthfirst.integer >= 2)
7917         {
7918                 R_DrawModelsDepth();
7919                 if (r_timereport_active)
7920                         R_TimeReport("modeldepth");
7921         }
7922
7923         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7924         {
7925                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7926                 if (r_timereport_active)
7927                         R_TimeReport("world");
7928         }
7929
7930         // don't let sound skip if going slow
7931         if (r_refdef.scene.extraupdate)
7932                 S_ExtraUpdate ();
7933
7934         R_DrawModels();
7935         if (r_timereport_active)
7936                 R_TimeReport("models");
7937
7938         // don't let sound skip if going slow
7939         if (r_refdef.scene.extraupdate)
7940                 S_ExtraUpdate ();
7941
7942         if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7943         {
7944                 R_DrawModelShadows();
7945                 R_ResetViewRendering3D();
7946                 // don't let sound skip if going slow
7947                 if (r_refdef.scene.extraupdate)
7948                         S_ExtraUpdate ();
7949         }
7950
7951         if (!r_shadow_usingdeferredprepass)
7952         {
7953                 R_Shadow_DrawLights();
7954                 if (r_timereport_active)
7955                         R_TimeReport("rtlights");
7956         }
7957
7958         // don't let sound skip if going slow
7959         if (r_refdef.scene.extraupdate)
7960                 S_ExtraUpdate ();
7961
7962         if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7963         {
7964                 R_DrawModelShadows();
7965                 R_ResetViewRendering3D();
7966                 // don't let sound skip if going slow
7967                 if (r_refdef.scene.extraupdate)
7968                         S_ExtraUpdate ();
7969         }
7970
7971         if (cl.csqc_vidvars.drawworld)
7972         {
7973                 if (cl_decals_newsystem.integer)
7974                 {
7975                         R_DrawModelDecals();
7976                         if (r_timereport_active)
7977                                 R_TimeReport("modeldecals");
7978                 }
7979                 else
7980                 {
7981                         R_DrawDecals();
7982                         if (r_timereport_active)
7983                                 R_TimeReport("decals");
7984                 }
7985
7986                 R_DrawParticles();
7987                 if (r_timereport_active)
7988                         R_TimeReport("particles");
7989
7990                 R_DrawExplosions();
7991                 if (r_timereport_active)
7992                         R_TimeReport("explosions");
7993
7994                 R_DrawLightningBeams();
7995                 if (r_timereport_active)
7996                         R_TimeReport("lightning");
7997         }
7998
7999         VM_CL_AddPolygonsToMeshQueue();
8000
8001         if (r_refdef.view.showdebug)
8002         {
8003                 if (cl_locs_show.integer)
8004                 {
8005                         R_DrawLocs();
8006                         if (r_timereport_active)
8007                                 R_TimeReport("showlocs");
8008                 }
8009
8010                 if (r_drawportals.integer)
8011                 {
8012                         R_DrawPortals();
8013                         if (r_timereport_active)
8014                                 R_TimeReport("portals");
8015                 }
8016
8017                 if (r_showbboxes.value > 0)
8018                 {
8019                         R_DrawEntityBBoxes();
8020                         if (r_timereport_active)
8021                                 R_TimeReport("bboxes");
8022                 }
8023         }
8024
8025         R_MeshQueue_RenderTransparent();
8026         if (r_timereport_active)
8027                 R_TimeReport("drawtrans");
8028
8029         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))
8030         {
8031                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
8032                 if (r_timereport_active)
8033                         R_TimeReport("worlddebug");
8034                 R_DrawModelsDebug();
8035                 if (r_timereport_active)
8036                         R_TimeReport("modeldebug");
8037         }
8038
8039         if (cl.csqc_vidvars.drawworld)
8040         {
8041                 R_Shadow_DrawCoronas();
8042                 if (r_timereport_active)
8043                         R_TimeReport("coronas");
8044         }
8045
8046         // don't let sound skip if going slow
8047         if (r_refdef.scene.extraupdate)
8048                 S_ExtraUpdate ();
8049
8050         R_ResetViewRendering2D();
8051 }
8052
8053 static const unsigned short bboxelements[36] =
8054 {
8055         5, 1, 3, 5, 3, 7,
8056         6, 2, 0, 6, 0, 4,
8057         7, 3, 2, 7, 2, 6,
8058         4, 0, 1, 4, 1, 5,
8059         4, 5, 7, 4, 7, 6,
8060         1, 0, 2, 1, 2, 3,
8061 };
8062
8063 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
8064 {
8065         int i;
8066         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
8067
8068         RSurf_ActiveWorldEntity();
8069
8070         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8071         GL_DepthMask(false);
8072         GL_DepthRange(0, 1);
8073         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8074         R_Mesh_ResetTextureState();
8075
8076         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
8077         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
8078         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
8079         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
8080         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
8081         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
8082         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
8083         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
8084         R_FillColors(color4f, 8, cr, cg, cb, ca);
8085         if (r_refdef.fogenabled)
8086         {
8087                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
8088                 {
8089                         f1 = RSurf_FogVertex(v);
8090                         f2 = 1 - f1;
8091                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
8092                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
8093                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
8094                 }
8095         }
8096         R_Mesh_VertexPointer(vertex3f, 0, 0);
8097         R_Mesh_ColorPointer(color4f, 0, 0);
8098         R_Mesh_ResetTextureState();
8099         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8100         R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
8101 }
8102
8103 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8104 {
8105         int i;
8106         float color[4];
8107         prvm_edict_t *edict;
8108         prvm_prog_t *prog_save = prog;
8109
8110         // this function draws bounding boxes of server entities
8111         if (!sv.active)
8112                 return;
8113
8114         GL_CullFace(GL_NONE);
8115         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8116
8117         prog = 0;
8118         SV_VM_Begin();
8119         for (i = 0;i < numsurfaces;i++)
8120         {
8121                 edict = PRVM_EDICT_NUM(surfacelist[i]);
8122                 switch ((int)edict->fields.server->solid)
8123                 {
8124                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
8125                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
8126                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
8127                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
8128                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
8129                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
8130                 }
8131                 color[3] *= r_showbboxes.value;
8132                 color[3] = bound(0, color[3], 1);
8133                 GL_DepthTest(!r_showdisabledepthtest.integer);
8134                 GL_CullFace(r_refdef.view.cullface_front);
8135                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
8136         }
8137         SV_VM_End();
8138         prog = prog_save;
8139 }
8140
8141 static void R_DrawEntityBBoxes(void)
8142 {
8143         int i;
8144         prvm_edict_t *edict;
8145         vec3_t center;
8146         prvm_prog_t *prog_save = prog;
8147
8148         // this function draws bounding boxes of server entities
8149         if (!sv.active)
8150                 return;
8151
8152         prog = 0;
8153         SV_VM_Begin();
8154         for (i = 0;i < prog->num_edicts;i++)
8155         {
8156                 edict = PRVM_EDICT_NUM(i);
8157                 if (edict->priv.server->free)
8158                         continue;
8159                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
8160                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
8161                         continue;
8162                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
8163                         continue;
8164                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
8165                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
8166         }
8167         SV_VM_End();
8168         prog = prog_save;
8169 }
8170
8171 static const int nomodelelement3i[24] =
8172 {
8173         5, 2, 0,
8174         5, 1, 2,
8175         5, 0, 3,
8176         5, 3, 1,
8177         0, 2, 4,
8178         2, 1, 4,
8179         3, 0, 4,
8180         1, 3, 4
8181 };
8182
8183 static const unsigned short nomodelelement3s[24] =
8184 {
8185         5, 2, 0,
8186         5, 1, 2,
8187         5, 0, 3,
8188         5, 3, 1,
8189         0, 2, 4,
8190         2, 1, 4,
8191         3, 0, 4,
8192         1, 3, 4
8193 };
8194
8195 static const float nomodelvertex3f[6*3] =
8196 {
8197         -16,   0,   0,
8198          16,   0,   0,
8199           0, -16,   0,
8200           0,  16,   0,
8201           0,   0, -16,
8202           0,   0,  16
8203 };
8204
8205 static const float nomodelcolor4f[6*4] =
8206 {
8207         0.0f, 0.0f, 0.5f, 1.0f,
8208         0.0f, 0.0f, 0.5f, 1.0f,
8209         0.0f, 0.5f, 0.0f, 1.0f,
8210         0.0f, 0.5f, 0.0f, 1.0f,
8211         0.5f, 0.0f, 0.0f, 1.0f,
8212         0.5f, 0.0f, 0.0f, 1.0f
8213 };
8214
8215 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8216 {
8217         int i;
8218         float f1, f2, *c;
8219         float color4f[6*4];
8220
8221         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);
8222
8223         // this is only called once per entity so numsurfaces is always 1, and
8224         // surfacelist is always {0}, so this code does not handle batches
8225
8226         if (rsurface.ent_flags & RENDER_ADDITIVE)
8227         {
8228                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
8229                 GL_DepthMask(false);
8230         }
8231         else if (rsurface.colormod[3] < 1)
8232         {
8233                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8234                 GL_DepthMask(false);
8235         }
8236         else
8237         {
8238                 GL_BlendFunc(GL_ONE, GL_ZERO);
8239                 GL_DepthMask(true);
8240         }
8241         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8242         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8243         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8244         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8245         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8246         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
8247         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8248         R_Mesh_ColorPointer(color4f, 0, 0);
8249         for (i = 0, c = color4f;i < 6;i++, c += 4)
8250         {
8251                 c[0] *= rsurface.colormod[0];
8252                 c[1] *= rsurface.colormod[1];
8253                 c[2] *= rsurface.colormod[2];
8254                 c[3] *= rsurface.colormod[3];
8255         }
8256         if (r_refdef.fogenabled)
8257         {
8258                 for (i = 0, c = color4f;i < 6;i++, c += 4)
8259                 {
8260                         f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
8261                         f2 = 1 - f1;
8262                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8263                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8264                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8265                 }
8266         }
8267         R_Mesh_ResetTextureState();
8268         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
8269 }
8270
8271 void R_DrawNoModel(entity_render_t *ent)
8272 {
8273         vec3_t org;
8274         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8275         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8276                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8277         else
8278                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8279 }
8280
8281 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8282 {
8283         vec3_t right1, right2, diff, normal;
8284
8285         VectorSubtract (org2, org1, normal);
8286
8287         // calculate 'right' vector for start
8288         VectorSubtract (r_refdef.view.origin, org1, diff);
8289         CrossProduct (normal, diff, right1);
8290         VectorNormalize (right1);
8291
8292         // calculate 'right' vector for end
8293         VectorSubtract (r_refdef.view.origin, org2, diff);
8294         CrossProduct (normal, diff, right2);
8295         VectorNormalize (right2);
8296
8297         vert[ 0] = org1[0] + width * right1[0];
8298         vert[ 1] = org1[1] + width * right1[1];
8299         vert[ 2] = org1[2] + width * right1[2];
8300         vert[ 3] = org1[0] - width * right1[0];
8301         vert[ 4] = org1[1] - width * right1[1];
8302         vert[ 5] = org1[2] - width * right1[2];
8303         vert[ 6] = org2[0] - width * right2[0];
8304         vert[ 7] = org2[1] - width * right2[1];
8305         vert[ 8] = org2[2] - width * right2[2];
8306         vert[ 9] = org2[0] + width * right2[0];
8307         vert[10] = org2[1] + width * right2[1];
8308         vert[11] = org2[2] + width * right2[2];
8309 }
8310
8311 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)
8312 {
8313         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8314         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8315         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8316         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8317         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8318         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8319         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8320         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8321         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8322         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8323         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8324         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8325 }
8326
8327 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8328 {
8329         int i;
8330         float *vertex3f;
8331         float v[3];
8332         VectorSet(v, x, y, z);
8333         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8334                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8335                         break;
8336         if (i == mesh->numvertices)
8337         {
8338                 if (mesh->numvertices < mesh->maxvertices)
8339                 {
8340                         VectorCopy(v, vertex3f);
8341                         mesh->numvertices++;
8342                 }
8343                 return mesh->numvertices;
8344         }
8345         else
8346                 return i;
8347 }
8348
8349 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8350 {
8351         int i;
8352         int *e, element[3];
8353         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8354         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8355         e = mesh->element3i + mesh->numtriangles * 3;
8356         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8357         {
8358                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8359                 if (mesh->numtriangles < mesh->maxtriangles)
8360                 {
8361                         *e++ = element[0];
8362                         *e++ = element[1];
8363                         *e++ = element[2];
8364                         mesh->numtriangles++;
8365                 }
8366                 element[1] = element[2];
8367         }
8368 }
8369
8370 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8371 {
8372         int i;
8373         int *e, element[3];
8374         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8375         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8376         e = mesh->element3i + mesh->numtriangles * 3;
8377         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8378         {
8379                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8380                 if (mesh->numtriangles < mesh->maxtriangles)
8381                 {
8382                         *e++ = element[0];
8383                         *e++ = element[1];
8384                         *e++ = element[2];
8385                         mesh->numtriangles++;
8386                 }
8387                 element[1] = element[2];
8388         }
8389 }
8390
8391 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8392 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8393 {
8394         int planenum, planenum2;
8395         int w;
8396         int tempnumpoints;
8397         mplane_t *plane, *plane2;
8398         double maxdist;
8399         double temppoints[2][256*3];
8400         // figure out how large a bounding box we need to properly compute this brush
8401         maxdist = 0;
8402         for (w = 0;w < numplanes;w++)
8403                 maxdist = max(maxdist, fabs(planes[w].dist));
8404         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8405         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8406         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8407         {
8408                 w = 0;
8409                 tempnumpoints = 4;
8410                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8411                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8412                 {
8413                         if (planenum2 == planenum)
8414                                 continue;
8415                         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);
8416                         w = !w;
8417                 }
8418                 if (tempnumpoints < 3)
8419                         continue;
8420                 // generate elements forming a triangle fan for this polygon
8421                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8422         }
8423 }
8424
8425 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)
8426 {
8427         texturelayer_t *layer;
8428         layer = t->currentlayers + t->currentnumlayers++;
8429         layer->type = type;
8430         layer->depthmask = depthmask;
8431         layer->blendfunc1 = blendfunc1;
8432         layer->blendfunc2 = blendfunc2;
8433         layer->texture = texture;
8434         layer->texmatrix = *matrix;
8435         layer->color[0] = r;
8436         layer->color[1] = g;
8437         layer->color[2] = b;
8438         layer->color[3] = a;
8439 }
8440
8441 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8442 {
8443         double index, f;
8444         index = parms[2] + r_refdef.scene.time * parms[3];
8445         index -= floor(index);
8446         switch (func)
8447         {
8448         default:
8449         case Q3WAVEFUNC_NONE:
8450         case Q3WAVEFUNC_NOISE:
8451         case Q3WAVEFUNC_COUNT:
8452                 f = 0;
8453                 break;
8454         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8455         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8456         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8457         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8458         case Q3WAVEFUNC_TRIANGLE:
8459                 index *= 4;
8460                 f = index - floor(index);
8461                 if (index < 1)
8462                         f = f;
8463                 else if (index < 2)
8464                         f = 1 - f;
8465                 else if (index < 3)
8466                         f = -f;
8467                 else
8468                         f = -(1 - f);
8469                 break;
8470         }
8471         return (float)(parms[0] + parms[1] * f);
8472 }
8473
8474 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8475 {
8476         int w, h, idx;
8477         float f;
8478         float tcmat[12];
8479         matrix4x4_t matrix, temp;
8480         switch(tcmod->tcmod)
8481         {
8482                 case Q3TCMOD_COUNT:
8483                 case Q3TCMOD_NONE:
8484                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8485                                 matrix = r_waterscrollmatrix;
8486                         else
8487                                 matrix = identitymatrix;
8488                         break;
8489                 case Q3TCMOD_ENTITYTRANSLATE:
8490                         // this is used in Q3 to allow the gamecode to control texcoord
8491                         // scrolling on the entity, which is not supported in darkplaces yet.
8492                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8493                         break;
8494                 case Q3TCMOD_ROTATE:
8495                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8496                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
8497                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8498                         break;
8499                 case Q3TCMOD_SCALE:
8500                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8501                         break;
8502                 case Q3TCMOD_SCROLL:
8503                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
8504                         break;
8505                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8506                         w = (int) tcmod->parms[0];
8507                         h = (int) tcmod->parms[1];
8508                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
8509                         f = f - floor(f);
8510                         idx = (int) floor(f * w * h);
8511                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8512                         break;
8513                 case Q3TCMOD_STRETCH:
8514                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8515                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8516                         break;
8517                 case Q3TCMOD_TRANSFORM:
8518                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8519                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8520                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8521                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8522                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8523                         break;
8524                 case Q3TCMOD_TURBULENT:
8525                         // this is handled in the RSurf_PrepareVertices function
8526                         matrix = identitymatrix;
8527                         break;
8528         }
8529         temp = *texmatrix;
8530         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8531 }
8532
8533 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8534 {
8535         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
8536         char name[MAX_QPATH];
8537         skinframe_t *skinframe;
8538         unsigned char pixels[296*194];
8539         strlcpy(cache->name, skinname, sizeof(cache->name));
8540         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8541         if (developer_loading.integer)
8542                 Con_Printf("loading %s\n", name);
8543         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8544         if (!skinframe || !skinframe->base)
8545         {
8546                 unsigned char *f;
8547                 fs_offset_t filesize;
8548                 skinframe = NULL;
8549                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8550                 if (f)
8551                 {
8552                         if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
8553                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8554                         Mem_Free(f);
8555                 }
8556         }
8557         cache->skinframe = skinframe;
8558 }
8559
8560 texture_t *R_GetCurrentTexture(texture_t *t)
8561 {
8562         int i;
8563         const entity_render_t *ent = rsurface.entity;
8564         dp_model_t *model = ent->model;
8565         q3shaderinfo_layer_tcmod_t *tcmod;
8566
8567         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
8568                 return t->currentframe;
8569         t->update_lastrenderframe = r_textureframe;
8570         t->update_lastrenderentity = (void *)ent;
8571
8572         // switch to an alternate material if this is a q1bsp animated material
8573         {
8574                 texture_t *texture = t;
8575                 int s = rsurface.ent_skinnum;
8576                 if ((unsigned int)s >= (unsigned int)model->numskins)
8577                         s = 0;
8578                 if (model->skinscenes)
8579                 {
8580                         if (model->skinscenes[s].framecount > 1)
8581                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8582                         else
8583                                 s = model->skinscenes[s].firstframe;
8584                 }
8585                 if (s > 0)
8586                         t = t + s * model->num_surfaces;
8587                 if (t->animated)
8588                 {
8589                         // use an alternate animation if the entity's frame is not 0,
8590                         // and only if the texture has an alternate animation
8591                         if (rsurface.ent_alttextures && t->anim_total[1])
8592                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
8593                         else
8594                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
8595                 }
8596                 texture->currentframe = t;
8597         }
8598
8599         // update currentskinframe to be a qw skin or animation frame
8600         if (rsurface.ent_qwskin >= 0)
8601         {
8602                 i = rsurface.ent_qwskin;
8603                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8604                 {
8605                         r_qwskincache_size = cl.maxclients;
8606                         if (r_qwskincache)
8607                                 Mem_Free(r_qwskincache);
8608                         r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8609                 }
8610                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8611                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8612                 t->currentskinframe = r_qwskincache[i].skinframe;
8613                 if (t->currentskinframe == NULL)
8614                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8615         }
8616         else if (t->numskinframes >= 2)
8617                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8618         if (t->backgroundnumskinframes >= 2)
8619                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
8620
8621         t->currentmaterialflags = t->basematerialflags;
8622         t->currentalpha = rsurface.colormod[3];
8623         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
8624                 t->currentalpha *= r_wateralpha.value;
8625         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
8626                 t->currentalpha *= t->r_water_wateralpha;
8627         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
8628                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
8629         if (!(rsurface.ent_flags & RENDER_LIGHT))
8630                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8631         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8632         {
8633                 // pick a model lighting mode
8634                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8635                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8636                 else
8637                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8638         }
8639         if (rsurface.ent_flags & RENDER_ADDITIVE)
8640                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8641         else if (t->currentalpha < 1)
8642                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8643         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8644                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8645         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8646                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8647         if (t->backgroundnumskinframes)
8648                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8649         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8650         {
8651                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
8652                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8653         }
8654         else
8655                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
8656         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8657                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8658
8659         // there is no tcmod
8660         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8661         {
8662                 t->currenttexmatrix = r_waterscrollmatrix;
8663                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8664         }
8665         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8666         {
8667                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8668                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8669         }
8670
8671         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8672                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8673         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8674                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8675
8676         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8677         if (t->currentskinframe->qpixels)
8678                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8679         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8680         if (!t->basetexture)
8681                 t->basetexture = r_texture_notexture;
8682         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8683         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8684         t->nmaptexture = t->currentskinframe->nmap;
8685         if (!t->nmaptexture)
8686                 t->nmaptexture = r_texture_blanknormalmap;
8687         t->glosstexture = r_texture_black;
8688         t->glowtexture = t->currentskinframe->glow;
8689         t->fogtexture = t->currentskinframe->fog;
8690         if (t->backgroundnumskinframes)
8691         {
8692                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8693                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8694                 t->backgroundglosstexture = r_texture_black;
8695                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8696                 if (!t->backgroundnmaptexture)
8697                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8698         }
8699         else
8700         {
8701                 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
8702                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8703                 t->backgroundglosstexture = r_texture_black;
8704                 t->backgroundglowtexture = NULL;
8705         }
8706         t->specularpower = r_shadow_glossexponent.value;
8707         // TODO: store reference values for these in the texture?
8708         t->specularscale = 0;
8709         if (r_shadow_gloss.integer > 0)
8710         {
8711                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8712                 {
8713                         if (r_shadow_glossintensity.value > 0)
8714                         {
8715                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8716                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8717                                 t->specularscale = r_shadow_glossintensity.value;
8718                         }
8719                 }
8720                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8721                 {
8722                         t->glosstexture = r_texture_white;
8723                         t->backgroundglosstexture = r_texture_white;
8724                         t->specularscale = r_shadow_gloss2intensity.value;
8725                         t->specularpower = r_shadow_gloss2exponent.value;
8726                 }
8727         }
8728         t->specularscale *= t->specularscalemod;
8729         t->specularpower *= t->specularpowermod;
8730
8731         // lightmaps mode looks bad with dlights using actual texturing, so turn
8732         // off the colormap and glossmap, but leave the normalmap on as it still
8733         // accurately represents the shading involved
8734         if (gl_lightmaps.integer)
8735         {
8736                 t->basetexture = r_texture_grey128;
8737                 t->pantstexture = r_texture_black;
8738                 t->shirttexture = r_texture_black;
8739                 t->nmaptexture = r_texture_blanknormalmap;
8740                 t->glosstexture = r_texture_black;
8741                 t->glowtexture = NULL;
8742                 t->fogtexture = NULL;
8743                 t->backgroundbasetexture = NULL;
8744                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8745                 t->backgroundglosstexture = r_texture_black;
8746                 t->backgroundglowtexture = NULL;
8747                 t->specularscale = 0;
8748                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8749         }
8750
8751         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8752         VectorClear(t->dlightcolor);
8753         t->currentnumlayers = 0;
8754         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8755         {
8756                 int blendfunc1, blendfunc2;
8757                 qboolean depthmask;
8758                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8759                 {
8760                         blendfunc1 = GL_SRC_ALPHA;
8761                         blendfunc2 = GL_ONE;
8762                 }
8763                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8764                 {
8765                         blendfunc1 = GL_SRC_ALPHA;
8766                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8767                 }
8768                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8769                 {
8770                         blendfunc1 = t->customblendfunc[0];
8771                         blendfunc2 = t->customblendfunc[1];
8772                 }
8773                 else
8774                 {
8775                         blendfunc1 = GL_ONE;
8776                         blendfunc2 = GL_ZERO;
8777                 }
8778                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8779                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8780                 {
8781                         // fullbright is not affected by r_refdef.lightmapintensity
8782                         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]);
8783                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8784                                 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]);
8785                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8786                                 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]);
8787                 }
8788                 else
8789                 {
8790                         vec3_t ambientcolor;
8791                         float colorscale;
8792                         // set the color tint used for lights affecting this surface
8793                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8794                         colorscale = 2;
8795                         // q3bsp has no lightmap updates, so the lightstylevalue that
8796                         // would normally be baked into the lightmap must be
8797                         // applied to the color
8798                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8799                         if (model->type == mod_brushq3)
8800                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8801                         colorscale *= r_refdef.lightmapintensity;
8802                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8803                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8804                         // basic lit geometry
8805                         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]);
8806                         // add pants/shirt if needed
8807                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8808                                 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]);
8809                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8810                                 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]);
8811                         // now add ambient passes if needed
8812                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8813                         {
8814                                 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]);
8815                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8816                                         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]);
8817                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8818                                         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]);
8819                         }
8820                 }
8821                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8822                         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]);
8823                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8824                 {
8825                         // if this is opaque use alpha blend which will darken the earlier
8826                         // passes cheaply.
8827                         //
8828                         // if this is an alpha blended material, all the earlier passes
8829                         // were darkened by fog already, so we only need to add the fog
8830                         // color ontop through the fog mask texture
8831                         //
8832                         // if this is an additive blended material, all the earlier passes
8833                         // were darkened by fog already, and we should not add fog color
8834                         // (because the background was not darkened, there is no fog color
8835                         // that was lost behind it).
8836                         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]);
8837                 }
8838         }
8839
8840         return t->currentframe;
8841 }
8842
8843 rsurfacestate_t rsurface;
8844
8845 void R_Mesh_ResizeArrays(int newvertices)
8846 {
8847         float *base;
8848         if (rsurface.array_size >= newvertices)
8849                 return;
8850         if (rsurface.array_modelvertex3f)
8851                 Mem_Free(rsurface.array_modelvertex3f);
8852         rsurface.array_size = (newvertices + 1023) & ~1023;
8853         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
8854         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
8855         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
8856         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
8857         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
8858         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
8859         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
8860         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
8861         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
8862         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
8863         rsurface.array_color4f           = base + rsurface.array_size * 27;
8864         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
8865 }
8866
8867 void RSurf_ActiveWorldEntity(void)
8868 {
8869         dp_model_t *model = r_refdef.scene.worldmodel;
8870         //if (rsurface.entity == r_refdef.scene.worldentity)
8871         //      return;
8872         rsurface.entity = r_refdef.scene.worldentity;
8873         rsurface.skeleton = NULL;
8874         rsurface.ent_skinnum = 0;
8875         rsurface.ent_qwskin = -1;
8876         rsurface.ent_shadertime = 0;
8877         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8878         if (rsurface.array_size < model->surfmesh.num_vertices)
8879                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
8880         rsurface.matrix = identitymatrix;
8881         rsurface.inversematrix = identitymatrix;
8882         rsurface.matrixscale = 1;
8883         rsurface.inversematrixscale = 1;
8884         R_EntityMatrix(&identitymatrix);
8885         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8886         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8887         rsurface.fograngerecip = r_refdef.fograngerecip;
8888         rsurface.fogheightfade = r_refdef.fogheightfade;
8889         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8890         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8891         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8892         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8893         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8894         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8895         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8896         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8897         rsurface.colormod[3] = 1;
8898         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);
8899         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8900         rsurface.frameblend[0].lerp = 1;
8901         rsurface.ent_alttextures = false;
8902         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8903         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8904         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8905         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
8906         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8907         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8908         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
8909         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8910         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8911         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
8912         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8913         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8914         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
8915         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8916         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8917         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
8918         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8919         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8920         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
8921         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8922         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8923         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
8924         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8925         rsurface.modelelement3i = model->surfmesh.data_element3i;
8926         rsurface.modelelement3s = model->surfmesh.data_element3s;
8927         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
8928         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
8929         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8930         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
8931         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
8932         rsurface.modelsurfaces = model->data_surfaces;
8933         rsurface.generatedvertex = false;
8934         rsurface.vertex3f  = rsurface.modelvertex3f;
8935         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
8936         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8937         rsurface.svector3f = rsurface.modelsvector3f;
8938         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
8939         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8940         rsurface.tvector3f = rsurface.modeltvector3f;
8941         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
8942         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8943         rsurface.normal3f  = rsurface.modelnormal3f;
8944         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
8945         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8946         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
8947 }
8948
8949 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8950 {
8951         dp_model_t *model = ent->model;
8952         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8953         //      return;
8954         rsurface.entity = (entity_render_t *)ent;
8955         rsurface.skeleton = ent->skeleton;
8956         rsurface.ent_skinnum = ent->skinnum;
8957         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;
8958         rsurface.ent_shadertime = ent->shadertime;
8959         rsurface.ent_flags = ent->flags;
8960         if (rsurface.array_size < model->surfmesh.num_vertices)
8961                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
8962         rsurface.matrix = ent->matrix;
8963         rsurface.inversematrix = ent->inversematrix;
8964         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8965         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8966         R_EntityMatrix(&rsurface.matrix);
8967         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8968         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8969         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8970         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8971         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8972         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8973         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8974         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8975         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8976         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8977         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8978         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8979         rsurface.colormod[3] = ent->alpha;
8980         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8981         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8982         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8983         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8984         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8985         if (ent->model->brush.submodel && !prepass)
8986         {
8987                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8988                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8989         }
8990         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
8991         {
8992                 if (ent->animcache_vertex3f && !r_framedata_failed)
8993                 {
8994                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8995                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8996                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8997                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8998                 }
8999                 else if (wanttangents)
9000                 {
9001                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9002                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9003                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9004                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9005                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
9006                 }
9007                 else if (wantnormals)
9008                 {
9009                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9010                         rsurface.modelsvector3f = NULL;
9011                         rsurface.modeltvector3f = NULL;
9012                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9013                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
9014                 }
9015                 else
9016                 {
9017                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9018                         rsurface.modelsvector3f = NULL;
9019                         rsurface.modeltvector3f = NULL;
9020                         rsurface.modelnormal3f = NULL;
9021                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
9022                 }
9023                 rsurface.modelvertex3f_bufferobject = 0;
9024                 rsurface.modelvertex3f_bufferoffset = 0;
9025                 rsurface.modelsvector3f_bufferobject = 0;
9026                 rsurface.modelsvector3f_bufferoffset = 0;
9027                 rsurface.modeltvector3f_bufferobject = 0;
9028                 rsurface.modeltvector3f_bufferoffset = 0;
9029                 rsurface.modelnormal3f_bufferobject = 0;
9030                 rsurface.modelnormal3f_bufferoffset = 0;
9031                 rsurface.generatedvertex = true;
9032         }
9033         else
9034         {
9035                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
9036                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9037                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9038                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9039                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9040                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9041                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9042                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9043                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9044                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
9045                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9046                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9047                 rsurface.generatedvertex = false;
9048         }
9049         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
9050         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9051         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9052         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
9053         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9054         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9055         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
9056         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9057         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9058         rsurface.modelelement3i = model->surfmesh.data_element3i;
9059         rsurface.modelelement3s = model->surfmesh.data_element3s;
9060         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9061         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9062         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9063         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9064         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9065         rsurface.modelsurfaces = model->data_surfaces;
9066         rsurface.vertex3f  = rsurface.modelvertex3f;
9067         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9068         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9069         rsurface.svector3f = rsurface.modelsvector3f;
9070         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9071         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9072         rsurface.tvector3f = rsurface.modeltvector3f;
9073         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9074         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9075         rsurface.normal3f  = rsurface.modelnormal3f;
9076         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9077         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9078         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9079 }
9080
9081 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)
9082 {
9083         rsurface.entity = r_refdef.scene.worldentity;
9084         rsurface.skeleton = NULL;
9085         rsurface.ent_skinnum = 0;
9086         rsurface.ent_qwskin = -1;
9087         rsurface.ent_shadertime = shadertime;
9088         rsurface.ent_flags = entflags;
9089         rsurface.modelnum_vertices = numvertices;
9090         rsurface.modelnum_triangles = numtriangles;
9091         if (rsurface.array_size < rsurface.modelnum_vertices)
9092                 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
9093         rsurface.matrix = *matrix;
9094         rsurface.inversematrix = *inversematrix;
9095         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9096         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9097         R_EntityMatrix(&rsurface.matrix);
9098         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9099         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9100         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9101         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9102         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9103         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9104         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9105         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9106         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9107         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9108         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9109         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
9110         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);
9111         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9112         rsurface.frameblend[0].lerp = 1;
9113         rsurface.ent_alttextures = false;
9114         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9115         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9116         if (wanttangents)
9117         {
9118                 rsurface.modelvertex3f = vertex3f;
9119                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
9120                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
9121                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9122         }
9123         else if (wantnormals)
9124         {
9125                 rsurface.modelvertex3f = vertex3f;
9126                 rsurface.modelsvector3f = NULL;
9127                 rsurface.modeltvector3f = NULL;
9128                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9129         }
9130         else
9131         {
9132                 rsurface.modelvertex3f = vertex3f;
9133                 rsurface.modelsvector3f = NULL;
9134                 rsurface.modeltvector3f = NULL;
9135                 rsurface.modelnormal3f = NULL;
9136         }
9137         rsurface.modelvertex3f_bufferobject = 0;
9138         rsurface.modelvertex3f_bufferoffset = 0;
9139         rsurface.modelsvector3f_bufferobject = 0;
9140         rsurface.modelsvector3f_bufferoffset = 0;
9141         rsurface.modeltvector3f_bufferobject = 0;
9142         rsurface.modeltvector3f_bufferoffset = 0;
9143         rsurface.modelnormal3f_bufferobject = 0;
9144         rsurface.modelnormal3f_bufferoffset = 0;
9145         rsurface.generatedvertex = true;
9146         rsurface.modellightmapcolor4f  = color4f;
9147         rsurface.modellightmapcolor4f_bufferobject = 0;
9148         rsurface.modellightmapcolor4f_bufferoffset = 0;
9149         rsurface.modeltexcoordtexture2f  = texcoord2f;
9150         rsurface.modeltexcoordtexture2f_bufferobject = 0;
9151         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9152         rsurface.modeltexcoordlightmap2f  = NULL;
9153         rsurface.modeltexcoordlightmap2f_bufferobject = 0;
9154         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9155         rsurface.modelelement3i = element3i;
9156         rsurface.modelelement3s = element3s;
9157         rsurface.modelelement3i_bufferobject = 0;
9158         rsurface.modelelement3s_bufferobject = 0;
9159         rsurface.modellightmapoffsets = NULL;
9160         rsurface.modelsurfaces = NULL;
9161         rsurface.vertex3f  = rsurface.modelvertex3f;
9162         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9163         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9164         rsurface.svector3f = rsurface.modelsvector3f;
9165         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9166         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9167         rsurface.tvector3f = rsurface.modeltvector3f;
9168         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9169         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9170         rsurface.normal3f  = rsurface.modelnormal3f;
9171         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9172         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9173         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9174
9175         if (rsurface.modelnum_vertices && rsurface.modelelement3i)
9176         {
9177                 if ((wantnormals || wanttangents) && !normal3f)
9178                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9179                 if (wanttangents && !svector3f)
9180                         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);
9181         }
9182 }
9183
9184 float RSurf_FogPoint(const float *v)
9185 {
9186         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9187         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9188         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9189         float FogHeightFade = r_refdef.fogheightfade;
9190         float fogfrac;
9191         unsigned int fogmasktableindex;
9192         if (r_refdef.fogplaneviewabove)
9193                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9194         else
9195                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9196         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9197         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9198 }
9199
9200 float RSurf_FogVertex(const float *v)
9201 {
9202         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9203         float FogPlaneViewDist = rsurface.fogplaneviewdist;
9204         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9205         float FogHeightFade = rsurface.fogheightfade;
9206         float fogfrac;
9207         unsigned int fogmasktableindex;
9208         if (r_refdef.fogplaneviewabove)
9209                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9210         else
9211                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9212         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9213         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9214 }
9215
9216 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9217 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9218 {
9219         int deformindex;
9220         int texturesurfaceindex;
9221         int i, j;
9222         float amplitude;
9223         float animpos;
9224         float scale;
9225         const float *v1, *in_tc;
9226         float *out_tc;
9227         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9228         float waveparms[4];
9229         q3shaderinfo_deform_t *deform;
9230         // 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
9231         if (rsurface.generatedvertex)
9232         {
9233                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
9234                         generatenormals = true;
9235                 for (i = 0;i < Q3MAXDEFORMS;i++)
9236                 {
9237                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
9238                         {
9239                                 generatetangents = true;
9240                                 generatenormals = true;
9241                         }
9242                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
9243                                 generatenormals = true;
9244                 }
9245                 if (generatenormals && !rsurface.modelnormal3f)
9246                 {
9247                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9248                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
9249                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
9250                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9251                 }
9252                 if (generatetangents && !rsurface.modelsvector3f)
9253                 {
9254                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9255                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
9256                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
9257                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9258                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
9259                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
9260                         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);
9261                 }
9262         }
9263         rsurface.vertex3f  = rsurface.modelvertex3f;
9264         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9265         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9266         rsurface.svector3f = rsurface.modelsvector3f;
9267         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9268         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9269         rsurface.tvector3f = rsurface.modeltvector3f;
9270         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9271         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9272         rsurface.normal3f  = rsurface.modelnormal3f;
9273         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9274         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9275         // if vertices are deformed (sprite flares and things in maps, possibly
9276         // water waves, bulges and other deformations), generate them into
9277         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
9278         // (may be static model data or generated data for an animated model, or
9279         //  the previous deform pass)
9280         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
9281         {
9282                 switch (deform->deform)
9283                 {
9284                 default:
9285                 case Q3DEFORM_PROJECTIONSHADOW:
9286                 case Q3DEFORM_TEXT0:
9287                 case Q3DEFORM_TEXT1:
9288                 case Q3DEFORM_TEXT2:
9289                 case Q3DEFORM_TEXT3:
9290                 case Q3DEFORM_TEXT4:
9291                 case Q3DEFORM_TEXT5:
9292                 case Q3DEFORM_TEXT6:
9293                 case Q3DEFORM_TEXT7:
9294                 case Q3DEFORM_NONE:
9295                         break;
9296                 case Q3DEFORM_AUTOSPRITE:
9297                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9298                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9299                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9300                         VectorNormalize(newforward);
9301                         VectorNormalize(newright);
9302                         VectorNormalize(newup);
9303                         // make deformed versions of only the model vertices used by the specified surfaces
9304                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9305                         {
9306                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9307                                 // a single autosprite surface can contain multiple sprites...
9308                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9309                                 {
9310                                         VectorClear(center);
9311                                         for (i = 0;i < 4;i++)
9312                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9313                                         VectorScale(center, 0.25f, center);
9314                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
9315                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
9316                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
9317                                         for (i = 0;i < 4;i++)
9318                                         {
9319                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
9320                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9321                                         }
9322                                 }
9323                                 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);
9324                                 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);
9325                         }
9326                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9327                         rsurface.vertex3f_bufferobject = 0;
9328                         rsurface.vertex3f_bufferoffset = 0;
9329                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9330                         rsurface.svector3f_bufferobject = 0;
9331                         rsurface.svector3f_bufferoffset = 0;
9332                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9333                         rsurface.tvector3f_bufferobject = 0;
9334                         rsurface.tvector3f_bufferoffset = 0;
9335                         rsurface.normal3f = rsurface.array_deformednormal3f;
9336                         rsurface.normal3f_bufferobject = 0;
9337                         rsurface.normal3f_bufferoffset = 0;
9338                         break;
9339                 case Q3DEFORM_AUTOSPRITE2:
9340                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9341                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9342                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9343                         VectorNormalize(newforward);
9344                         VectorNormalize(newright);
9345                         VectorNormalize(newup);
9346                         // make deformed versions of only the model vertices used by the specified surfaces
9347                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9348                         {
9349                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9350                                 const float *v1, *v2;
9351                                 vec3_t start, end;
9352                                 float f, l;
9353                                 struct
9354                                 {
9355                                         float length2;
9356                                         const float *v1;
9357                                         const float *v2;
9358                                 }
9359                                 shortest[2];
9360                                 memset(shortest, 0, sizeof(shortest));
9361                                 // a single autosprite surface can contain multiple sprites...
9362                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9363                                 {
9364                                         VectorClear(center);
9365                                         for (i = 0;i < 4;i++)
9366                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9367                                         VectorScale(center, 0.25f, center);
9368                                         // find the two shortest edges, then use them to define the
9369                                         // axis vectors for rotating around the central axis
9370                                         for (i = 0;i < 6;i++)
9371                                         {
9372                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
9373                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
9374 #if 0
9375                                                 Debug_PolygonBegin(NULL, 0);
9376                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
9377                                                 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);
9378                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
9379                                                 Debug_PolygonEnd();
9380 #endif
9381                                                 l = VectorDistance2(v1, v2);
9382                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9383                                                 if (v1[2] != v2[2])
9384                                                         l += (1.0f / 1024.0f);
9385                                                 if (shortest[0].length2 > l || i == 0)
9386                                                 {
9387                                                         shortest[1] = shortest[0];
9388                                                         shortest[0].length2 = l;
9389                                                         shortest[0].v1 = v1;
9390                                                         shortest[0].v2 = v2;
9391                                                 }
9392                                                 else if (shortest[1].length2 > l || i == 1)
9393                                                 {
9394                                                         shortest[1].length2 = l;
9395                                                         shortest[1].v1 = v1;
9396                                                         shortest[1].v2 = v2;
9397                                                 }
9398                                         }
9399                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9400                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9401 #if 0
9402                                         Debug_PolygonBegin(NULL, 0);
9403                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
9404                                         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);
9405                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
9406                                         Debug_PolygonEnd();
9407 #endif
9408                                         // this calculates the right vector from the shortest edge
9409                                         // and the up vector from the edge midpoints
9410                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9411                                         VectorNormalize(right);
9412                                         VectorSubtract(end, start, up);
9413                                         VectorNormalize(up);
9414                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9415                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9416                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9417                                         VectorNegate(forward, forward);
9418                                         VectorReflect(forward, 0, up, forward);
9419                                         VectorNormalize(forward);
9420                                         CrossProduct(up, forward, newright);
9421                                         VectorNormalize(newright);
9422 #if 0
9423                                         Debug_PolygonBegin(NULL, 0);
9424                                         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);
9425                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
9426                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
9427                                         Debug_PolygonEnd();
9428 #endif
9429 #if 0
9430                                         Debug_PolygonBegin(NULL, 0);
9431                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
9432                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
9433                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
9434                                         Debug_PolygonEnd();
9435 #endif
9436                                         // rotate the quad around the up axis vector, this is made
9437                                         // especially easy by the fact we know the quad is flat,
9438                                         // so we only have to subtract the center position and
9439                                         // measure distance along the right vector, and then
9440                                         // multiply that by the newright vector and add back the
9441                                         // center position
9442                                         // we also need to subtract the old position to undo the
9443                                         // displacement from the center, which we do with a
9444                                         // DotProduct, the subtraction/addition of center is also
9445                                         // optimized into DotProducts here
9446                                         l = DotProduct(right, center);
9447                                         for (i = 0;i < 4;i++)
9448                                         {
9449                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
9450                                                 f = DotProduct(right, v1) - l;
9451                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9452                                         }
9453                                 }
9454                                 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);
9455                                 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);
9456                         }
9457                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9458                         rsurface.vertex3f_bufferobject = 0;
9459                         rsurface.vertex3f_bufferoffset = 0;
9460                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9461                         rsurface.svector3f_bufferobject = 0;
9462                         rsurface.svector3f_bufferoffset = 0;
9463                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9464                         rsurface.tvector3f_bufferobject = 0;
9465                         rsurface.tvector3f_bufferoffset = 0;
9466                         rsurface.normal3f = rsurface.array_deformednormal3f;
9467                         rsurface.normal3f_bufferobject = 0;
9468                         rsurface.normal3f_bufferoffset = 0;
9469                         break;
9470                 case Q3DEFORM_NORMAL:
9471                         // deform the normals to make reflections wavey
9472                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9473                         {
9474                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9475                                 for (j = 0;j < surface->num_vertices;j++)
9476                                 {
9477                                         float vertex[3];
9478                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
9479                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
9480                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
9481                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9482                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9483                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9484                                         VectorNormalize(normal);
9485                                 }
9486                                 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);
9487                         }
9488                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9489                         rsurface.svector3f_bufferobject = 0;
9490                         rsurface.svector3f_bufferoffset = 0;
9491                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9492                         rsurface.tvector3f_bufferobject = 0;
9493                         rsurface.tvector3f_bufferoffset = 0;
9494                         rsurface.normal3f = rsurface.array_deformednormal3f;
9495                         rsurface.normal3f_bufferobject = 0;
9496                         rsurface.normal3f_bufferoffset = 0;
9497                         break;
9498                 case Q3DEFORM_WAVE:
9499                         // deform vertex array to make wavey water and flags and such
9500                         waveparms[0] = deform->waveparms[0];
9501                         waveparms[1] = deform->waveparms[1];
9502                         waveparms[2] = deform->waveparms[2];
9503                         waveparms[3] = deform->waveparms[3];
9504                         // this is how a divisor of vertex influence on deformation
9505                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9506                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9507                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9508                         {
9509                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9510                                 for (j = 0;j < surface->num_vertices;j++)
9511                                 {
9512                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
9513                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9514                                         // if the wavefunc depends on time, evaluate it per-vertex
9515                                         if (waveparms[3])
9516                                         {
9517                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
9518                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9519                                         }
9520                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9521                                 }
9522                         }
9523                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9524                         rsurface.vertex3f_bufferobject = 0;
9525                         rsurface.vertex3f_bufferoffset = 0;
9526                         break;
9527                 case Q3DEFORM_BULGE:
9528                         // deform vertex array to make the surface have moving bulges
9529                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9530                         {
9531                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9532                                 for (j = 0;j < surface->num_vertices;j++)
9533                                 {
9534                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
9535                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9536                                 }
9537                         }
9538                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9539                         rsurface.vertex3f_bufferobject = 0;
9540                         rsurface.vertex3f_bufferoffset = 0;
9541                         break;
9542                 case Q3DEFORM_MOVE:
9543                         // deform vertex array
9544                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9545                         VectorScale(deform->parms, scale, waveparms);
9546                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9547                         {
9548                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9549                                 for (j = 0;j < surface->num_vertices;j++)
9550                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9551                         }
9552                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9553                         rsurface.vertex3f_bufferobject = 0;
9554                         rsurface.vertex3f_bufferoffset = 0;
9555                         break;
9556                 }
9557         }
9558         // generate texcoords based on the chosen texcoord source
9559         switch(rsurface.texture->tcgen.tcgen)
9560         {
9561         default:
9562         case Q3TCGEN_TEXTURE:
9563                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
9564                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
9565                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9566                 break;
9567         case Q3TCGEN_LIGHTMAP:
9568                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
9569                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
9570                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
9571                 break;
9572         case Q3TCGEN_VECTOR:
9573                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9574                 {
9575                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9576                         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)
9577                         {
9578                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
9579                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
9580                         }
9581                 }
9582                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9583                 rsurface.texcoordtexture2f_bufferobject  = 0;
9584                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9585                 break;
9586         case Q3TCGEN_ENVIRONMENT:
9587                 // make environment reflections using a spheremap
9588                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9589                 {
9590                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9591                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
9592                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
9593                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
9594                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
9595                         {
9596                                 // identical to Q3A's method, but executed in worldspace so
9597                                 // carried models can be shiny too
9598
9599                                 float viewer[3], d, reflected[3], worldreflected[3];
9600
9601                                 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
9602                                 // VectorNormalize(viewer);
9603
9604                                 d = DotProduct(normal, viewer);
9605
9606                                 reflected[0] = normal[0]*2*d - viewer[0];
9607                                 reflected[1] = normal[1]*2*d - viewer[1];
9608                                 reflected[2] = normal[2]*2*d - viewer[2];
9609                                 // note: this is proportinal to viewer, so we can normalize later
9610
9611                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9612                                 VectorNormalize(worldreflected);
9613
9614                                 // note: this sphere map only uses world x and z!
9615                                 // so positive and negative y will LOOK THE SAME.
9616                                 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
9617                                 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
9618                         }
9619                 }
9620                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9621                 rsurface.texcoordtexture2f_bufferobject  = 0;
9622                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9623                 break;
9624         }
9625         // the only tcmod that needs software vertex processing is turbulent, so
9626         // check for it here and apply the changes if needed
9627         // and we only support that as the first one
9628         // (handling a mixture of turbulent and other tcmods would be problematic
9629         //  without punting it entirely to a software path)
9630         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9631         {
9632                 amplitude = rsurface.texture->tcmods[0].parms[1];
9633                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
9634                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9635                 {
9636                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9637                         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)
9638                         {
9639                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9640                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9641                         }
9642                 }
9643                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9644                 rsurface.texcoordtexture2f_bufferobject  = 0;
9645                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9646         }
9647         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
9648         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
9649         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9650         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
9651 }
9652
9653 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9654 {
9655         int i, j;
9656         const msurface_t *surface = texturesurfacelist[0];
9657         const msurface_t *surface2;
9658         int firstvertex;
9659         int endvertex;
9660         int numvertices;
9661         int numtriangles;
9662         // TODO: lock all array ranges before render, rather than on each surface
9663         if (texturenumsurfaces == 1)
9664                 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);
9665         else if (r_batchmode.integer == 2)
9666         {
9667                 #define MAXBATCHTRIANGLES 4096
9668                 int batchtriangles = 0;
9669                 static int batchelements[MAXBATCHTRIANGLES*3];
9670                 for (i = 0;i < texturenumsurfaces;i = j)
9671                 {
9672                         surface = texturesurfacelist[i];
9673                         j = i + 1;
9674                         if (surface->num_triangles > MAXBATCHTRIANGLES)
9675                         {
9676                                 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);
9677                                 continue;
9678                         }
9679                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9680                         batchtriangles = surface->num_triangles;
9681                         firstvertex = surface->num_firstvertex;
9682                         endvertex = surface->num_firstvertex + surface->num_vertices;
9683                         for (;j < texturenumsurfaces;j++)
9684                         {
9685                                 surface2 = texturesurfacelist[j];
9686                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9687                                         break;
9688                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9689                                 batchtriangles += surface2->num_triangles;
9690                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
9691                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9692                         }
9693                         surface2 = texturesurfacelist[j-1];
9694                         numvertices = endvertex - firstvertex;
9695                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9696                 }
9697         }
9698         else if (r_batchmode.integer == 1)
9699         {
9700                 for (i = 0;i < texturenumsurfaces;i = j)
9701                 {
9702                         surface = texturesurfacelist[i];
9703                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9704                                 if (texturesurfacelist[j] != surface2)
9705                                         break;
9706                         surface2 = texturesurfacelist[j-1];
9707                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9708                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9709                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9710                 }
9711         }
9712         else
9713         {
9714                 for (i = 0;i < texturenumsurfaces;i++)
9715                 {
9716                         surface = texturesurfacelist[i];
9717                         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);
9718                 }
9719         }
9720 }
9721
9722 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
9723 {
9724         switch(vid.renderpath)
9725         {
9726         case RENDERPATH_CGGL:
9727 #ifdef SUPPORTCG
9728                 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
9729                 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
9730 #endif
9731                 break;
9732         case RENDERPATH_GL20:
9733                 if (r_glsl_permutation->loc_Texture_Lightmap  >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
9734                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
9735                 break;
9736         case RENDERPATH_GL13:
9737         case RENDERPATH_GL11:
9738                 R_Mesh_TexBind(0, surface->lightmaptexture);
9739                 break;
9740         }
9741 }
9742
9743 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
9744 {
9745         // pick the closest matching water plane and bind textures
9746         int planeindex, vertexindex;
9747         float d, bestd;
9748         vec3_t vert;
9749         const float *v;
9750         r_waterstate_waterplane_t *p, *bestp;
9751         bestd = 0;
9752         bestp = NULL;
9753         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9754         {
9755                 d = 0;
9756                 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
9757                 {
9758                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9759                         d += fabs(PlaneDiff(vert, &p->plane));
9760                 }
9761                 if (bestd > d || !bestp)
9762                 {
9763                         bestd = d;
9764                         bestp = p;
9765                 }
9766         }
9767         switch(vid.renderpath)
9768         {
9769         case RENDERPATH_CGGL:
9770 #ifdef SUPPORTCG
9771                 if (r_cg_permutation->fp_Texture_Refraction) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR
9772                 if (r_cg_permutation->fp_Texture_Reflection) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR
9773 #endif
9774                 break;
9775         case RENDERPATH_GL20:
9776                 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
9777                 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
9778                 break;
9779         case RENDERPATH_GL13:
9780         case RENDERPATH_GL11:
9781                 break;
9782         }
9783 }
9784
9785 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9786 {
9787         int i;
9788         const msurface_t *surface;
9789         if (r_waterstate.renderingscene)
9790                 return;
9791         for (i = 0;i < texturenumsurfaces;i++)
9792         {
9793                 surface = texturesurfacelist[i];
9794                 RSurf_BindLightmapForSurface(surface);
9795                 RSurf_BindReflectionForSurface(surface);
9796                 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);
9797         }
9798 }
9799
9800 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9801 {
9802         int i;
9803         int j;
9804         const msurface_t *surface = texturesurfacelist[0];
9805         const msurface_t *surface2;
9806         int firstvertex;
9807         int endvertex;
9808         int numvertices;
9809         int numtriangles;
9810         if (texturenumsurfaces == 1)
9811         {
9812                 RSurf_BindLightmapForSurface(surface);
9813                 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);
9814         }
9815         else if (r_batchmode.integer == 2)
9816         {
9817 #define MAXBATCHTRIANGLES 4096
9818                 int batchtriangles = 0;
9819                 static int batchelements[MAXBATCHTRIANGLES*3];
9820                 for (i = 0;i < texturenumsurfaces;i = j)
9821                 {
9822                         surface = texturesurfacelist[i];
9823                         RSurf_BindLightmapForSurface(surface);
9824                         j = i + 1;
9825                         if (surface->num_triangles > MAXBATCHTRIANGLES)
9826                         {
9827                                 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);
9828                                 continue;
9829                         }
9830                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9831                         batchtriangles = surface->num_triangles;
9832                         firstvertex = surface->num_firstvertex;
9833                         endvertex = surface->num_firstvertex + surface->num_vertices;
9834                         for (;j < texturenumsurfaces;j++)
9835                         {
9836                                 surface2 = texturesurfacelist[j];
9837                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9838                                         break;
9839                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9840                                 batchtriangles += surface2->num_triangles;
9841                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
9842                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9843                         }
9844                         surface2 = texturesurfacelist[j-1];
9845                         numvertices = endvertex - firstvertex;
9846                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9847                 }
9848         }
9849         else if (r_batchmode.integer == 1)
9850         {
9851 #if 0
9852                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
9853                 for (i = 0;i < texturenumsurfaces;i = j)
9854                 {
9855                         surface = texturesurfacelist[i];
9856                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9857                                 if (texturesurfacelist[j] != surface2)
9858                                         break;
9859                         Con_Printf(" %i", j - i);
9860                 }
9861                 Con_Printf("\n");
9862                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
9863 #endif
9864                 for (i = 0;i < texturenumsurfaces;i = j)
9865                 {
9866                         surface = texturesurfacelist[i];
9867                         RSurf_BindLightmapForSurface(surface);
9868                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9869                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
9870                                         break;
9871 #if 0
9872                         Con_Printf(" %i", j - i);
9873 #endif
9874                         surface2 = texturesurfacelist[j-1];
9875                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9876                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9877                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9878                 }
9879 #if 0
9880                 Con_Printf("\n");
9881 #endif
9882         }
9883         else
9884         {
9885                 for (i = 0;i < texturenumsurfaces;i++)
9886                 {
9887                         surface = texturesurfacelist[i];
9888                         RSurf_BindLightmapForSurface(surface);
9889                         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);
9890                 }
9891         }
9892 }
9893
9894 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9895 {
9896         int j;
9897         int texturesurfaceindex;
9898         if (r_showsurfaces.integer == 2)
9899         {
9900                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9901                 {
9902                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9903                         for (j = 0;j < surface->num_triangles;j++)
9904                         {
9905                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
9906                                 GL_Color(f, f, f, 1);
9907                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9908                         }
9909                 }
9910         }
9911         else
9912         {
9913                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9914                 {
9915                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9916                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
9917                         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);
9918                         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);
9919                 }
9920         }
9921 }
9922
9923 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9924 {
9925         int texturesurfaceindex;
9926         int i;
9927         const float *v;
9928         float *c2;
9929         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9930         {
9931                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9932                 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)
9933                 {
9934                         c2[0] = 0.5;
9935                         c2[1] = 0.5;
9936                         c2[2] = 0.5;
9937                         c2[3] = 1;
9938                 }
9939         }
9940         rsurface.lightmapcolor4f = rsurface.array_color4f;
9941         rsurface.lightmapcolor4f_bufferobject = 0;
9942         rsurface.lightmapcolor4f_bufferoffset = 0;
9943 }
9944
9945 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9946 {
9947         int texturesurfaceindex;
9948         int i;
9949         float f;
9950         const float *v;
9951         const float *c;
9952         float *c2;
9953         if (rsurface.lightmapcolor4f)
9954         {
9955                 // generate color arrays for the surfaces in this list
9956                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9957                 {
9958                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9959                         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)
9960                         {
9961                                 f = RSurf_FogVertex(v);
9962                                 c2[0] = c[0] * f;
9963                                 c2[1] = c[1] * f;
9964                                 c2[2] = c[2] * f;
9965                                 c2[3] = c[3];
9966                         }
9967                 }
9968         }
9969         else
9970         {
9971                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9972                 {
9973                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9974                         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)
9975                         {
9976                                 f = RSurf_FogVertex(v);
9977                                 c2[0] = f;
9978                                 c2[1] = f;
9979                                 c2[2] = f;
9980                                 c2[3] = 1;
9981                         }
9982                 }
9983         }
9984         rsurface.lightmapcolor4f = rsurface.array_color4f;
9985         rsurface.lightmapcolor4f_bufferobject = 0;
9986         rsurface.lightmapcolor4f_bufferoffset = 0;
9987 }
9988
9989 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9990 {
9991         int texturesurfaceindex;
9992         int i;
9993         float f;
9994         const float *v;
9995         const float *c;
9996         float *c2;
9997         if (!rsurface.lightmapcolor4f)
9998                 return;
9999         // generate color arrays for the surfaces in this list
10000         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10001         {
10002                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10003                 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)
10004                 {
10005                         f = RSurf_FogVertex(v);
10006                         c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10007                         c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10008                         c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10009                         c2[3] = c[3];
10010                 }
10011         }
10012         rsurface.lightmapcolor4f = rsurface.array_color4f;
10013         rsurface.lightmapcolor4f_bufferobject = 0;
10014         rsurface.lightmapcolor4f_bufferoffset = 0;
10015 }
10016
10017 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
10018 {
10019         int texturesurfaceindex;
10020         int i;
10021         const float *c;
10022         float *c2;
10023         if (!rsurface.lightmapcolor4f)
10024                 return;
10025         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10026         {
10027                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10028                 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)
10029                 {
10030                         c2[0] = c[0] * r;
10031                         c2[1] = c[1] * g;
10032                         c2[2] = c[2] * b;
10033                         c2[3] = c[3] * a;
10034                 }
10035         }
10036         rsurface.lightmapcolor4f = rsurface.array_color4f;
10037         rsurface.lightmapcolor4f_bufferobject = 0;
10038         rsurface.lightmapcolor4f_bufferoffset = 0;
10039 }
10040
10041 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10042 {
10043         int texturesurfaceindex;
10044         int i;
10045         const float *c;
10046         float *c2;
10047         if (!rsurface.lightmapcolor4f)
10048                 return;
10049         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10050         {
10051                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10052                 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)
10053                 {
10054                         c2[0] = c[0] + r_refdef.scene.ambient;
10055                         c2[1] = c[1] + r_refdef.scene.ambient;
10056                         c2[2] = c[2] + r_refdef.scene.ambient;
10057                         c2[3] = c[3];
10058                 }
10059         }
10060         rsurface.lightmapcolor4f = rsurface.array_color4f;
10061         rsurface.lightmapcolor4f_bufferobject = 0;
10062         rsurface.lightmapcolor4f_bufferoffset = 0;
10063 }
10064
10065 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10066 {
10067         // TODO: optimize
10068         rsurface.lightmapcolor4f = NULL;
10069         rsurface.lightmapcolor4f_bufferobject = 0;
10070         rsurface.lightmapcolor4f_bufferoffset = 0;
10071         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10072         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10073         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10074         GL_Color(r, g, b, a);
10075         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10076 }
10077
10078 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10079 {
10080         // TODO: optimize applyfog && applycolor case
10081         // just apply fog if necessary, and tint the fog color array if necessary
10082         rsurface.lightmapcolor4f = NULL;
10083         rsurface.lightmapcolor4f_bufferobject = 0;
10084         rsurface.lightmapcolor4f_bufferoffset = 0;
10085         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10086         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10087         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10088         GL_Color(r, g, b, a);
10089         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10090 }
10091
10092 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10093 {
10094         int texturesurfaceindex;
10095         int i;
10096         float *c;
10097         // TODO: optimize
10098         if (texturesurfacelist[0]->lightmapinfo)
10099         {
10100                 // generate color arrays for the surfaces in this list
10101                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10102                 {
10103                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10104                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
10105                         {
10106                                 if (surface->lightmapinfo->samples)
10107                                 {
10108                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
10109                                         float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
10110                                         VectorScale(lm, scale, c);
10111                                         if (surface->lightmapinfo->styles[1] != 255)
10112                                         {
10113                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
10114                                                 lm += size3;
10115                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
10116                                                 VectorMA(c, scale, lm, c);
10117                                                 if (surface->lightmapinfo->styles[2] != 255)
10118                                                 {
10119                                                         lm += size3;
10120                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
10121                                                         VectorMA(c, scale, lm, c);
10122                                                         if (surface->lightmapinfo->styles[3] != 255)
10123                                                         {
10124                                                                 lm += size3;
10125                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
10126                                                                 VectorMA(c, scale, lm, c);
10127                                                         }
10128                                                 }
10129                                         }
10130                                 }
10131                                 else
10132                                         VectorClear(c);
10133                                 c[3] = 1;
10134                         }
10135                 }
10136                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10137                 rsurface.lightmapcolor4f_bufferobject = 0;
10138                 rsurface.lightmapcolor4f_bufferoffset = 0;
10139         }
10140         else
10141         {
10142                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10143                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10144                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10145         }
10146         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10147         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10148         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10149         GL_Color(r, g, b, a);
10150         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10151 }
10152
10153 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
10154 {
10155         int texturesurfaceindex;
10156         int i;
10157         float f;
10158         float alpha;
10159         const float *v;
10160         const float *n;
10161         float *c;
10162         vec3_t ambientcolor;
10163         vec3_t diffusecolor;
10164         vec3_t lightdir;
10165         // TODO: optimize
10166         // model lighting
10167         VectorCopy(rsurface.modellight_lightdir, lightdir);
10168         f = 0.5f * r_refdef.lightmapintensity;
10169         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10170         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10171         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10172         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10173         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10174         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10175         alpha = *a;
10176         if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
10177         {
10178                 // generate color arrays for the surfaces in this list
10179                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10180                 {
10181                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10182                         int numverts = surface->num_vertices;
10183                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
10184                         n = rsurface.normal3f + 3 * surface->num_firstvertex;
10185                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
10186                         // q3-style directional shading
10187                         for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
10188                         {
10189                                 if ((f = DotProduct(n, lightdir)) > 0)
10190                                         VectorMA(ambientcolor, f, diffusecolor, c);
10191                                 else
10192                                         VectorCopy(ambientcolor, c);
10193                                 c[3] = alpha;
10194                         }
10195                 }
10196                 *r = 1;
10197                 *g = 1;
10198                 *b = 1;
10199                 *a = 1;
10200                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10201                 rsurface.lightmapcolor4f_bufferobject = 0;
10202                 rsurface.lightmapcolor4f_bufferoffset = 0;
10203                 *applycolor = false;
10204         }
10205         else
10206         {
10207                 *r = ambientcolor[0];
10208                 *g = ambientcolor[1];
10209                 *b = ambientcolor[2];
10210                 rsurface.lightmapcolor4f = NULL;
10211                 rsurface.lightmapcolor4f_bufferobject = 0;
10212                 rsurface.lightmapcolor4f_bufferoffset = 0;
10213         }
10214 }
10215
10216 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10217 {
10218         RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
10219         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10220         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10221         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10222         GL_Color(r, g, b, a);
10223         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10224 }
10225
10226 void RSurf_SetupDepthAndCulling(void)
10227 {
10228         // submodels are biased to avoid z-fighting with world surfaces that they
10229         // may be exactly overlapping (avoids z-fighting artifacts on certain
10230         // doors and things in Quake maps)
10231         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10232         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10233         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10234         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10235 }
10236
10237 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10238 {
10239         // transparent sky would be ridiculous
10240         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10241                 return;
10242         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10243         skyrenderlater = true;
10244         RSurf_SetupDepthAndCulling();
10245         GL_DepthMask(true);
10246         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10247         // skymasking on them, and Quake3 never did sky masking (unlike
10248         // software Quake and software Quake2), so disable the sky masking
10249         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10250         // and skymasking also looks very bad when noclipping outside the
10251         // level, so don't use it then either.
10252         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
10253         {
10254                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10255                 R_Mesh_ColorPointer(NULL, 0, 0);
10256                 R_Mesh_ResetTextureState();
10257                 if (skyrendermasked)
10258                 {
10259                         R_SetupShader_DepthOrShadow();
10260                         // depth-only (masking)
10261                         GL_ColorMask(0,0,0,0);
10262                         // just to make sure that braindead drivers don't draw
10263                         // anything despite that colormask...
10264                         GL_BlendFunc(GL_ZERO, GL_ONE);
10265                 }
10266                 else
10267                 {
10268                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10269                         // fog sky
10270                         GL_BlendFunc(GL_ONE, GL_ZERO);
10271                 }
10272                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10273                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10274                 if (skyrendermasked)
10275                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10276         }
10277         R_Mesh_ResetTextureState();
10278         GL_Color(1, 1, 1, 1);
10279 }
10280
10281 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10282 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10283 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10284 {
10285         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10286         if (prepass)
10287         {
10288                 // render screenspace normalmap to texture
10289                 GL_DepthMask(true);
10290                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
10291                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10292         }
10293         else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !r_waterstate.renderingscene)
10294         {
10295                 // render water or distortion background, then blend surface on top
10296                 GL_DepthMask(true);
10297                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
10298                 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10299                 GL_DepthMask(false);
10300                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
10301                 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10302         }
10303         else
10304         {
10305                 // render surface normally
10306                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10307                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
10308                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
10309                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10310                 else if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10311                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10312                 else
10313                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10314         }
10315 }
10316
10317 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10318 {
10319         // OpenGL 1.3 path - anything not completely ancient
10320         int texturesurfaceindex;
10321         qboolean applycolor;
10322         qboolean applyfog;
10323         int layerindex;
10324         const texturelayer_t *layer;
10325         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10326
10327         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10328         {
10329                 vec4_t layercolor;
10330                 int layertexrgbscale;
10331                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10332                 {
10333                         if (layerindex == 0)
10334                                 GL_AlphaTest(true);
10335                         else
10336                         {
10337                                 GL_AlphaTest(false);
10338                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10339                         }
10340                 }
10341                 GL_DepthMask(layer->depthmask && writedepth);
10342                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10343                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10344                 {
10345                         layertexrgbscale = 4;
10346                         VectorScale(layer->color, 0.25f, layercolor);
10347                 }
10348                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10349                 {
10350                         layertexrgbscale = 2;
10351                         VectorScale(layer->color, 0.5f, layercolor);
10352                 }
10353                 else
10354                 {
10355                         layertexrgbscale = 1;
10356                         VectorScale(layer->color, 1.0f, layercolor);
10357                 }
10358                 layercolor[3] = layer->color[3];
10359                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10360                 R_Mesh_ColorPointer(NULL, 0, 0);
10361                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10362                 switch (layer->type)
10363                 {
10364                 case TEXTURELAYERTYPE_LITTEXTURE:
10365                         // single-pass lightmapped texture with 2x rgbscale
10366                         //R_Mesh_TexBind(0, r_texture_white);
10367                         R_Mesh_TexMatrix(0, NULL);
10368                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10369                         R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10370                         R_Mesh_TexBind(1, layer->texture);
10371                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10372                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10373                         R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10374                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10375                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10376                         else if (rsurface.uselightmaptexture)
10377                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10378                         else
10379                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10380                         break;
10381                 case TEXTURELAYERTYPE_TEXTURE:
10382                         // singletexture unlit texture with transparency support
10383                         R_Mesh_TexBind(0, layer->texture);
10384                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10385                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10386                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10387                         R_Mesh_TexBind(1, 0);
10388                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10389                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10390                         break;
10391                 case TEXTURELAYERTYPE_FOG:
10392                         // singletexture fogging
10393                         if (layer->texture)
10394                         {
10395                                 R_Mesh_TexBind(0, layer->texture);
10396                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10397                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10398                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10399                         }
10400                         else
10401                         {
10402                                 R_Mesh_TexBind(0, 0);
10403                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10404                         }
10405                         R_Mesh_TexBind(1, 0);
10406                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10407                         // generate a color array for the fog pass
10408                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10409                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10410                         {
10411                                 int i;
10412                                 float f;
10413                                 const float *v;
10414                                 float *c;
10415                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10416                                 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)
10417                                 {
10418                                         f = 1 - RSurf_FogVertex(v);
10419                                         c[0] = layercolor[0];
10420                                         c[1] = layercolor[1];
10421                                         c[2] = layercolor[2];
10422                                         c[3] = f * layercolor[3];
10423                                 }
10424                         }
10425                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10426                         break;
10427                 default:
10428                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10429                 }
10430         }
10431         CHECKGLERROR
10432         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10433         {
10434                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10435                 GL_AlphaTest(false);
10436         }
10437 }
10438
10439 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10440 {
10441         // OpenGL 1.1 - crusty old voodoo path
10442         int texturesurfaceindex;
10443         qboolean applyfog;
10444         int layerindex;
10445         const texturelayer_t *layer;
10446         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10447
10448         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10449         {
10450                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10451                 {
10452                         if (layerindex == 0)
10453                                 GL_AlphaTest(true);
10454                         else
10455                         {
10456                                 GL_AlphaTest(false);
10457                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10458                         }
10459                 }
10460                 GL_DepthMask(layer->depthmask && writedepth);
10461                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10462                 R_Mesh_ColorPointer(NULL, 0, 0);
10463                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10464                 switch (layer->type)
10465                 {
10466                 case TEXTURELAYERTYPE_LITTEXTURE:
10467                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10468                         {
10469                                 // two-pass lit texture with 2x rgbscale
10470                                 // first the lightmap pass
10471                                 //R_Mesh_TexBind(0, r_texture_white);
10472                                 R_Mesh_TexMatrix(0, NULL);
10473                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10474                                 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10475                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10476                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10477                                 else if (rsurface.uselightmaptexture)
10478                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10479                                 else
10480                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10481                                 // then apply the texture to it
10482                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10483                                 R_Mesh_TexBind(0, layer->texture);
10484                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10485                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10486                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10487                                 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);
10488                         }
10489                         else
10490                         {
10491                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10492                                 R_Mesh_TexBind(0, layer->texture);
10493                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10494                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10495                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10496                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10497                                         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);
10498                                 else
10499                                         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);
10500                         }
10501                         break;
10502                 case TEXTURELAYERTYPE_TEXTURE:
10503                         // singletexture unlit texture with transparency support
10504                         R_Mesh_TexBind(0, layer->texture);
10505                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10506                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10507                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10508                         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);
10509                         break;
10510                 case TEXTURELAYERTYPE_FOG:
10511                         // singletexture fogging
10512                         if (layer->texture)
10513                         {
10514                                 R_Mesh_TexBind(0, layer->texture);
10515                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10516                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10517                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10518                         }
10519                         else
10520                         {
10521                                 R_Mesh_TexBind(0, 0);
10522                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10523                         }
10524                         // generate a color array for the fog pass
10525                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10526                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10527                         {
10528                                 int i;
10529                                 float f;
10530                                 const float *v;
10531                                 float *c;
10532                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10533                                 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)
10534                                 {
10535                                         f = 1 - RSurf_FogVertex(v);
10536                                         c[0] = layer->color[0];
10537                                         c[1] = layer->color[1];
10538                                         c[2] = layer->color[2];
10539                                         c[3] = f * layer->color[3];
10540                                 }
10541                         }
10542                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10543                         break;
10544                 default:
10545                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10546                 }
10547         }
10548         CHECKGLERROR
10549         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10550         {
10551                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10552                 GL_AlphaTest(false);
10553         }
10554 }
10555
10556 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10557 {
10558         float c[4];
10559
10560         GL_AlphaTest(false);
10561         R_Mesh_ColorPointer(NULL, 0, 0);
10562         R_Mesh_ResetTextureState();
10563         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10564
10565         if(rsurface.texture && rsurface.texture->currentskinframe)
10566         {
10567                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10568                 c[3] *= rsurface.texture->currentalpha;
10569         }
10570         else
10571         {
10572                 c[0] = 1;
10573                 c[1] = 0;
10574                 c[2] = 1;
10575                 c[3] = 1;
10576         }
10577
10578         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10579         {
10580                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10581                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10582                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10583         }
10584
10585         // brighten it up (as texture value 127 means "unlit")
10586         c[0] *= 2 * r_refdef.view.colorscale;
10587         c[1] *= 2 * r_refdef.view.colorscale;
10588         c[2] *= 2 * r_refdef.view.colorscale;
10589
10590         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10591                 c[3] *= r_wateralpha.value;
10592
10593         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10594         {
10595                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10596                 GL_DepthMask(false);
10597         }
10598         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10599         {
10600                 GL_BlendFunc(GL_ONE, GL_ONE);
10601                 GL_DepthMask(false);
10602         }
10603         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10604         {
10605                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10606                 GL_DepthMask(false);
10607         }
10608         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10609         {
10610                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10611                 GL_DepthMask(false);
10612         }
10613         else
10614         {
10615                 GL_BlendFunc(GL_ONE, GL_ZERO);
10616                 GL_DepthMask(writedepth);
10617         }
10618
10619         rsurface.lightmapcolor4f = NULL;
10620
10621         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10622         {
10623                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10624
10625                 rsurface.lightmapcolor4f = NULL;
10626                 rsurface.lightmapcolor4f_bufferobject = 0;
10627                 rsurface.lightmapcolor4f_bufferoffset = 0;
10628         }
10629         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10630         {
10631                 qboolean applycolor = true;
10632                 float one = 1.0;
10633
10634                 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10635
10636                 r_refdef.lightmapintensity = 1;
10637                 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
10638                 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10639         }
10640         else
10641         {
10642                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10643
10644                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10645                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10646                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10647         }
10648
10649         if(!rsurface.lightmapcolor4f)
10650                 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
10651
10652         RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
10653         RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
10654         if(r_refdef.fogenabled)
10655                 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
10656
10657         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10658         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10659 }
10660
10661 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10662 {
10663         CHECKGLERROR
10664         RSurf_SetupDepthAndCulling();
10665         if (r_showsurfaces.integer == 3 && !prepass)
10666         {
10667                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10668                 return;
10669         }
10670         switch (vid.renderpath)
10671         {
10672         case RENDERPATH_GL20:
10673         case RENDERPATH_CGGL:
10674                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10675                 break;
10676         case RENDERPATH_GL13:
10677                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10678                 break;
10679         case RENDERPATH_GL11:
10680                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10681                 break;
10682         }
10683         CHECKGLERROR
10684 }
10685
10686 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10687 {
10688         CHECKGLERROR
10689         RSurf_SetupDepthAndCulling();
10690         if (r_showsurfaces.integer == 3 && !prepass)
10691         {
10692                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10693                 return;
10694         }
10695         switch (vid.renderpath)
10696         {
10697         case RENDERPATH_GL20:
10698         case RENDERPATH_CGGL:
10699                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10700                 break;
10701         case RENDERPATH_GL13:
10702                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10703                 break;
10704         case RENDERPATH_GL11:
10705                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10706                 break;
10707         }
10708         CHECKGLERROR
10709 }
10710
10711 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10712 {
10713         int i, j;
10714         int texturenumsurfaces, endsurface;
10715         texture_t *texture;
10716         const msurface_t *surface;
10717         const msurface_t *texturesurfacelist[256];
10718
10719         // if the model is static it doesn't matter what value we give for
10720         // wantnormals and wanttangents, so this logic uses only rules applicable
10721         // to a model, knowing that they are meaningless otherwise
10722         if (ent == r_refdef.scene.worldentity)
10723                 RSurf_ActiveWorldEntity();
10724         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10725                 RSurf_ActiveModelEntity(ent, false, false, false);
10726         else
10727         {
10728                 switch (vid.renderpath)
10729                 {
10730                 case RENDERPATH_GL20:
10731                 case RENDERPATH_CGGL:
10732                         RSurf_ActiveModelEntity(ent, true, true, false);
10733                         break;
10734                 case RENDERPATH_GL13:
10735                 case RENDERPATH_GL11:
10736                         RSurf_ActiveModelEntity(ent, true, false, false);
10737                         break;
10738                 }
10739         }
10740
10741         if (r_transparentdepthmasking.integer)
10742         {
10743                 qboolean setup = false;
10744                 for (i = 0;i < numsurfaces;i = j)
10745                 {
10746                         j = i + 1;
10747                         surface = rsurface.modelsurfaces + surfacelist[i];
10748                         texture = surface->texture;
10749                         rsurface.texture = R_GetCurrentTexture(texture);
10750                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10751                         // scan ahead until we find a different texture
10752                         endsurface = min(i + 1024, numsurfaces);
10753                         texturenumsurfaces = 0;
10754                         texturesurfacelist[texturenumsurfaces++] = surface;
10755                         for (;j < endsurface;j++)
10756                         {
10757                                 surface = rsurface.modelsurfaces + surfacelist[j];
10758                                 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10759                                         break;
10760                                 texturesurfacelist[texturenumsurfaces++] = surface;
10761                         }
10762                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10763                                 continue;
10764                         // render the range of surfaces as depth
10765                         if (!setup)
10766                         {
10767                                 setup = true;
10768                                 GL_ColorMask(0,0,0,0);
10769                                 GL_Color(1,1,1,1);
10770                                 GL_DepthTest(true);
10771                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10772                                 GL_DepthMask(true);
10773                                 GL_AlphaTest(false);
10774                                 R_Mesh_ColorPointer(NULL, 0, 0);
10775                                 R_Mesh_ResetTextureState();
10776                                 R_SetupShader_DepthOrShadow();
10777                         }
10778                         RSurf_SetupDepthAndCulling();
10779                         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10780                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10781                 }
10782                 if (setup)
10783                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10784         }
10785
10786         for (i = 0;i < numsurfaces;i = j)
10787         {
10788                 j = i + 1;
10789                 surface = rsurface.modelsurfaces + surfacelist[i];
10790                 texture = surface->texture;
10791                 rsurface.texture = R_GetCurrentTexture(texture);
10792                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10793                 // scan ahead until we find a different texture
10794                 endsurface = min(i + 1024, numsurfaces);
10795                 texturenumsurfaces = 0;
10796                 texturesurfacelist[texturenumsurfaces++] = surface;
10797                 for (;j < endsurface;j++)
10798                 {
10799                         surface = rsurface.modelsurfaces + surfacelist[j];
10800                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10801                                 break;
10802                         texturesurfacelist[texturenumsurfaces++] = surface;
10803                 }
10804                 // render the range of surfaces
10805                 if (ent == r_refdef.scene.worldentity)
10806                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10807                 else
10808                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10809         }
10810         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10811         GL_AlphaTest(false);
10812 }
10813
10814 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10815 {
10816         // transparent surfaces get pushed off into the transparent queue
10817         int surfacelistindex;
10818         const msurface_t *surface;
10819         vec3_t tempcenter, center;
10820         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10821         {
10822                 surface = texturesurfacelist[surfacelistindex];
10823                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10824                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10825                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10826                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10827                 if (queueentity->transparent_offset) // transparent offset
10828                 {
10829                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10830                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10831                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10832                 }
10833                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10834         }
10835 }
10836
10837 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10838 {
10839         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10840         CHECKGLERROR
10841         if (depthonly)
10842         {
10843                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10844                         return;
10845                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10846                         return;
10847                 RSurf_SetupDepthAndCulling();
10848                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10849                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10850         }
10851         else if (prepass)
10852         {
10853                 if (!rsurface.texture->currentnumlayers)
10854                         return;
10855                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10856                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10857                 else
10858                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10859         }
10860         else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
10861         {
10862                 RSurf_SetupDepthAndCulling();
10863                 GL_AlphaTest(false);
10864                 R_Mesh_ColorPointer(NULL, 0, 0);
10865                 R_Mesh_ResetTextureState();
10866                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10867                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10868                 GL_DepthMask(true);
10869                 GL_BlendFunc(GL_ONE, GL_ZERO);
10870                 GL_Color(0, 0, 0, 1);
10871                 GL_DepthTest(writedepth);
10872                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10873         }
10874         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
10875         {
10876                 RSurf_SetupDepthAndCulling();
10877                 GL_AlphaTest(false);
10878                 R_Mesh_ColorPointer(NULL, 0, 0);
10879                 R_Mesh_ResetTextureState();
10880                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10881                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10882                 GL_DepthMask(true);
10883                 GL_BlendFunc(GL_ONE, GL_ZERO);
10884                 GL_DepthTest(true);
10885                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
10886         }
10887         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
10888                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10889         else if (!rsurface.texture->currentnumlayers)
10890                 return;
10891         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10892         {
10893                 // in the deferred case, transparent surfaces were queued during prepass
10894                 if (!r_shadow_usingdeferredprepass)
10895                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10896         }
10897         else
10898         {
10899                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10900                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10901         }
10902         CHECKGLERROR
10903 }
10904
10905 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10906 {
10907         int i, j;
10908         texture_t *texture;
10909         // break the surface list down into batches by texture and use of lightmapping
10910         for (i = 0;i < numsurfaces;i = j)
10911         {
10912                 j = i + 1;
10913                 // texture is the base texture pointer, rsurface.texture is the
10914                 // current frame/skin the texture is directing us to use (for example
10915                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10916                 // use skin 1 instead)
10917                 texture = surfacelist[i]->texture;
10918                 rsurface.texture = R_GetCurrentTexture(texture);
10919                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
10920                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10921                 {
10922                         // if this texture is not the kind we want, skip ahead to the next one
10923                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10924                                 ;
10925                         continue;
10926                 }
10927                 // simply scan ahead until we find a different texture or lightmap state
10928                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
10929                         ;
10930                 // render the range of surfaces
10931                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10932         }
10933 }
10934
10935 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10936 {
10937         CHECKGLERROR
10938         if (depthonly)
10939         {
10940                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10941                         return;
10942                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10943                         return;
10944                 RSurf_SetupDepthAndCulling();
10945                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10946                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10947         }
10948         else if (prepass)
10949         {
10950                 if (!rsurface.texture->currentnumlayers)
10951                         return;
10952                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10953                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10954                 else
10955                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10956         }
10957         else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
10958         {
10959                 RSurf_SetupDepthAndCulling();
10960                 GL_AlphaTest(false);
10961                 R_Mesh_ColorPointer(NULL, 0, 0);
10962                 R_Mesh_ResetTextureState();
10963                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10964                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10965                 GL_DepthMask(true);
10966                 GL_BlendFunc(GL_ONE, GL_ZERO);
10967                 GL_Color(0, 0, 0, 1);
10968                 GL_DepthTest(writedepth);
10969                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10970         }
10971         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10972         {
10973                 RSurf_SetupDepthAndCulling();
10974                 GL_AlphaTest(false);
10975                 R_Mesh_ColorPointer(NULL, 0, 0);
10976                 R_Mesh_ResetTextureState();
10977                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10978                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10979                 GL_DepthMask(true);
10980                 GL_BlendFunc(GL_ONE, GL_ZERO);
10981                 GL_DepthTest(true);
10982                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
10983         }
10984         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
10985                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10986         else if (!rsurface.texture->currentnumlayers)
10987                 return;
10988         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10989         {
10990                 // in the deferred case, transparent surfaces were queued during prepass
10991                 if (!r_shadow_usingdeferredprepass)
10992                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10993         }
10994         else
10995         {
10996                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10997                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10998         }
10999         CHECKGLERROR
11000 }
11001
11002 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11003 {
11004         int i, j;
11005         texture_t *texture;
11006         // break the surface list down into batches by texture and use of lightmapping
11007         for (i = 0;i < numsurfaces;i = j)
11008         {
11009                 j = i + 1;
11010                 // texture is the base texture pointer, rsurface.texture is the
11011                 // current frame/skin the texture is directing us to use (for example
11012                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11013                 // use skin 1 instead)
11014                 texture = surfacelist[i]->texture;
11015                 rsurface.texture = R_GetCurrentTexture(texture);
11016                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11017                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11018                 {
11019                         // if this texture is not the kind we want, skip ahead to the next one
11020                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11021                                 ;
11022                         continue;
11023                 }
11024                 // simply scan ahead until we find a different texture or lightmap state
11025                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11026                         ;
11027                 // render the range of surfaces
11028                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
11029         }
11030 }
11031
11032 float locboxvertex3f[6*4*3] =
11033 {
11034         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11035         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11036         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11037         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11038         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11039         1,0,0, 0,0,0, 0,1,0, 1,1,0
11040 };
11041
11042 unsigned short locboxelements[6*2*3] =
11043 {
11044          0, 1, 2, 0, 2, 3,
11045          4, 5, 6, 4, 6, 7,
11046          8, 9,10, 8,10,11,
11047         12,13,14, 12,14,15,
11048         16,17,18, 16,18,19,
11049         20,21,22, 20,22,23
11050 };
11051
11052 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11053 {
11054         int i, j;
11055         cl_locnode_t *loc = (cl_locnode_t *)ent;
11056         vec3_t mins, size;
11057         float vertex3f[6*4*3];
11058         CHECKGLERROR
11059         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11060         GL_DepthMask(false);
11061         GL_DepthRange(0, 1);
11062         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11063         GL_DepthTest(true);
11064         GL_CullFace(GL_NONE);
11065         R_EntityMatrix(&identitymatrix);
11066
11067         R_Mesh_VertexPointer(vertex3f, 0, 0);
11068         R_Mesh_ColorPointer(NULL, 0, 0);
11069         R_Mesh_ResetTextureState();
11070         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11071
11072         i = surfacelist[0];
11073         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11074                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11075                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11076                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11077
11078         if (VectorCompare(loc->mins, loc->maxs))
11079         {
11080                 VectorSet(size, 2, 2, 2);
11081                 VectorMA(loc->mins, -0.5f, size, mins);
11082         }
11083         else
11084         {
11085                 VectorCopy(loc->mins, mins);
11086                 VectorSubtract(loc->maxs, loc->mins, size);
11087         }
11088
11089         for (i = 0;i < 6*4*3;)
11090                 for (j = 0;j < 3;j++, i++)
11091                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11092
11093         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
11094 }
11095
11096 void R_DrawLocs(void)
11097 {
11098         int index;
11099         cl_locnode_t *loc, *nearestloc;
11100         vec3_t center;
11101         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11102         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11103         {
11104                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11105                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11106         }
11107 }
11108
11109 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11110 {
11111         if (decalsystem->decals)
11112                 Mem_Free(decalsystem->decals);
11113         memset(decalsystem, 0, sizeof(*decalsystem));
11114 }
11115
11116 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)
11117 {
11118         tridecal_t *decal;
11119         tridecal_t *decals;
11120         int i;
11121         int maxdecals;
11122
11123         // expand or initialize the system
11124         if (decalsystem->maxdecals <= decalsystem->numdecals)
11125         {
11126                 decalsystem_t old = *decalsystem;
11127                 qboolean useshortelements;
11128                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11129                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11130                 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)));
11131                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11132                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11133                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11134                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11135                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11136                 if (decalsystem->numdecals)
11137                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11138                 if (old.decals)
11139                         Mem_Free(old.decals);
11140                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11141                         decalsystem->element3i[i] = i;
11142                 if (useshortelements)
11143                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11144                                 decalsystem->element3s[i] = i;
11145         }
11146
11147         // grab a decal and search for another free slot for the next one
11148         maxdecals = decalsystem->maxdecals;
11149         decals = decalsystem->decals;
11150         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11151         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
11152                 ;
11153         decalsystem->freedecal = i;
11154         if (decalsystem->numdecals <= i)
11155                 decalsystem->numdecals = i + 1;
11156
11157         // initialize the decal
11158         decal->lived = 0;
11159         decal->triangleindex = triangleindex;
11160         decal->surfaceindex = surfaceindex;
11161         decal->decalsequence = decalsequence;
11162         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
11163         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
11164         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
11165         decal->color4ub[0][3] = 255;
11166         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
11167         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
11168         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
11169         decal->color4ub[1][3] = 255;
11170         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
11171         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
11172         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
11173         decal->color4ub[2][3] = 255;
11174         decal->vertex3f[0][0] = v0[0];
11175         decal->vertex3f[0][1] = v0[1];
11176         decal->vertex3f[0][2] = v0[2];
11177         decal->vertex3f[1][0] = v1[0];
11178         decal->vertex3f[1][1] = v1[1];
11179         decal->vertex3f[1][2] = v1[2];
11180         decal->vertex3f[2][0] = v2[0];
11181         decal->vertex3f[2][1] = v2[1];
11182         decal->vertex3f[2][2] = v2[2];
11183         decal->texcoord2f[0][0] = t0[0];
11184         decal->texcoord2f[0][1] = t0[1];
11185         decal->texcoord2f[1][0] = t1[0];
11186         decal->texcoord2f[1][1] = t1[1];
11187         decal->texcoord2f[2][0] = t2[0];
11188         decal->texcoord2f[2][1] = t2[1];
11189 }
11190
11191 extern cvar_t cl_decals_bias;
11192 extern cvar_t cl_decals_models;
11193 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11194 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)
11195 {
11196         matrix4x4_t projection;
11197         decalsystem_t *decalsystem;
11198         qboolean dynamic;
11199         dp_model_t *model;
11200         const float *vertex3f;
11201         const msurface_t *surface;
11202         const msurface_t *surfaces;
11203         const int *surfacelist;
11204         const texture_t *texture;
11205         int numvertices;
11206         int numtriangles;
11207         int numsurfacelist;
11208         int surfacelistindex;
11209         int surfaceindex;
11210         int triangleindex;
11211         int decalsurfaceindex;
11212         int cornerindex;
11213         int index;
11214         int numpoints;
11215         const int *e;
11216         float localorigin[3];
11217         float localnormal[3];
11218         float localmins[3];
11219         float localmaxs[3];
11220         float localsize;
11221         float ilocalsize;
11222         float v[9][3];
11223         float tc[9][2];
11224         float c[9][4];
11225         //float normal[3];
11226         float planes[6][4];
11227         float f;
11228         float points[2][9][3];
11229         float angles[3];
11230         float temp[3];
11231
11232         decalsystem = &ent->decalsystem;
11233         model = ent->model;
11234         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11235         {
11236                 R_DecalSystem_Reset(&ent->decalsystem);
11237                 return;
11238         }
11239
11240         if (!model->brush.data_nodes && !cl_decals_models.integer)
11241         {
11242                 if (decalsystem->model)
11243                         R_DecalSystem_Reset(decalsystem);
11244                 return;
11245         }
11246
11247         if (decalsystem->model != model)
11248                 R_DecalSystem_Reset(decalsystem);
11249         decalsystem->model = model;
11250
11251         RSurf_ActiveModelEntity(ent, false, false, false);
11252
11253         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11254         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11255         VectorNormalize(localnormal);
11256         localsize = worldsize*rsurface.inversematrixscale;
11257         ilocalsize = 1.0f / localsize;
11258         localmins[0] = localorigin[0] - localsize;
11259         localmins[1] = localorigin[1] - localsize;
11260         localmins[2] = localorigin[2] - localsize;
11261         localmaxs[0] = localorigin[0] + localsize;
11262         localmaxs[1] = localorigin[1] + localsize;
11263         localmaxs[2] = localorigin[2] + localsize;
11264
11265         //VectorCopy(localnormal, planes[4]);
11266         //VectorVectors(planes[4], planes[2], planes[0]);
11267         AnglesFromVectors(angles, localnormal, NULL, false);
11268         AngleVectors(angles, planes[0], planes[2], planes[4]);
11269         VectorNegate(planes[0], planes[1]);
11270         VectorNegate(planes[2], planes[3]);
11271         VectorNegate(planes[4], planes[5]);
11272         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11273         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11274         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11275         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11276         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11277         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11278
11279 #if 1
11280 // works
11281 {
11282         matrix4x4_t forwardprojection;
11283         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11284         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11285 }
11286 #else
11287 // broken
11288 {
11289         float projectionvector[4][3];
11290         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11291         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11292         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11293         projectionvector[0][0] = planes[0][0] * ilocalsize;
11294         projectionvector[0][1] = planes[1][0] * ilocalsize;
11295         projectionvector[0][2] = planes[2][0] * ilocalsize;
11296         projectionvector[1][0] = planes[0][1] * ilocalsize;
11297         projectionvector[1][1] = planes[1][1] * ilocalsize;
11298         projectionvector[1][2] = planes[2][1] * ilocalsize;
11299         projectionvector[2][0] = planes[0][2] * ilocalsize;
11300         projectionvector[2][1] = planes[1][2] * ilocalsize;
11301         projectionvector[2][2] = planes[2][2] * ilocalsize;
11302         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11303         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11304         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11305         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11306 }
11307 #endif
11308
11309         dynamic = model->surfmesh.isanimated;
11310         vertex3f = rsurface.modelvertex3f;
11311         numsurfacelist = model->nummodelsurfaces;
11312         surfacelist = model->sortedmodelsurfaces;
11313         surfaces = model->data_surfaces;
11314         for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11315         {
11316                 surfaceindex = surfacelist[surfacelistindex];
11317                 surface = surfaces + surfaceindex;
11318                 // skip transparent surfaces
11319                 texture = surface->texture;
11320                 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11321                         continue;
11322                 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11323                         continue;
11324                 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11325                         continue;
11326                 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
11327                 numvertices = surface->num_vertices;
11328                 numtriangles = surface->num_triangles;
11329                 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
11330                 {
11331                         for (cornerindex = 0;cornerindex < 3;cornerindex++)
11332                         {
11333                                 index = 3*e[cornerindex];
11334                                 VectorCopy(vertex3f + index, v[cornerindex]);
11335                         }
11336                         // cull backfaces
11337                         //TriangleNormal(v[0], v[1], v[2], normal);
11338                         //if (DotProduct(normal, localnormal) < 0.0f)
11339                         //      continue;
11340                         // clip by each of the box planes formed from the projection matrix
11341                         // if anything survives, we emit the decal
11342                         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]);
11343                         if (numpoints < 3)
11344                                 continue;
11345                         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]);
11346                         if (numpoints < 3)
11347                                 continue;
11348                         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]);
11349                         if (numpoints < 3)
11350                                 continue;
11351                         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]);
11352                         if (numpoints < 3)
11353                                 continue;
11354                         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]);
11355                         if (numpoints < 3)
11356                                 continue;
11357                         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]);
11358                         if (numpoints < 3)
11359                                 continue;
11360                         // some part of the triangle survived, so we have to accept it...
11361                         if (dynamic)
11362                         {
11363                                 // dynamic always uses the original triangle
11364                                 numpoints = 3;
11365                                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11366                                 {
11367                                         index = 3*e[cornerindex];
11368                                         VectorCopy(vertex3f + index, v[cornerindex]);
11369                                 }
11370                         }
11371                         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11372                         {
11373                                 // convert vertex positions to texcoords
11374                                 Matrix4x4_Transform(&projection, v[cornerindex], temp);
11375                                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11376                                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11377                                 // calculate distance fade from the projection origin
11378                                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11379                                 f = bound(0.0f, f, 1.0f);
11380                                 c[cornerindex][0] = r * f;
11381                                 c[cornerindex][1] = g * f;
11382                                 c[cornerindex][2] = b * f;
11383                                 c[cornerindex][3] = 1.0f;
11384                                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11385                         }
11386                         if (dynamic)
11387                                 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);
11388                         else
11389                                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11390                                         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);
11391                 }
11392         }
11393 }
11394
11395 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11396 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)
11397 {
11398         int renderentityindex;
11399         float worldmins[3];
11400         float worldmaxs[3];
11401         entity_render_t *ent;
11402
11403         if (!cl_decals_newsystem.integer)
11404                 return;
11405
11406         worldmins[0] = worldorigin[0] - worldsize;
11407         worldmins[1] = worldorigin[1] - worldsize;
11408         worldmins[2] = worldorigin[2] - worldsize;
11409         worldmaxs[0] = worldorigin[0] + worldsize;
11410         worldmaxs[1] = worldorigin[1] + worldsize;
11411         worldmaxs[2] = worldorigin[2] + worldsize;
11412
11413         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11414
11415         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11416         {
11417                 ent = r_refdef.scene.entities[renderentityindex];
11418                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11419                         continue;
11420
11421                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11422         }
11423 }
11424
11425 typedef struct r_decalsystem_splatqueue_s
11426 {
11427         vec3_t worldorigin;
11428         vec3_t worldnormal;
11429         float color[4];
11430         float tcrange[4];
11431         float worldsize;
11432         int decalsequence;
11433 }
11434 r_decalsystem_splatqueue_t;
11435
11436 int r_decalsystem_numqueued = 0;
11437 #define MAX_DECALSYSTEM_QUEUE 1024
11438 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11439
11440 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)
11441 {
11442         r_decalsystem_splatqueue_t *queue;
11443
11444         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11445                 return;
11446
11447         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11448         VectorCopy(worldorigin, queue->worldorigin);
11449         VectorCopy(worldnormal, queue->worldnormal);
11450         Vector4Set(queue->color, r, g, b, a);
11451         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11452         queue->worldsize = worldsize;
11453         queue->decalsequence = cl.decalsequence++;
11454 }
11455
11456 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11457 {
11458         int i;
11459         r_decalsystem_splatqueue_t *queue;
11460
11461         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11462                 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);
11463         r_decalsystem_numqueued = 0;
11464 }
11465
11466 extern cvar_t cl_decals_max;
11467 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11468 {
11469         int i;
11470         decalsystem_t *decalsystem = &ent->decalsystem;
11471         int numdecals;
11472         int killsequence;
11473         tridecal_t *decal;
11474         float frametime;
11475         float lifetime;
11476
11477         if (!decalsystem->numdecals)
11478                 return;
11479
11480         if (r_showsurfaces.integer)
11481                 return;
11482
11483         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11484         {
11485                 R_DecalSystem_Reset(decalsystem);
11486                 return;
11487         }
11488
11489         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11490         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11491
11492         if (decalsystem->lastupdatetime)
11493                 frametime = (cl.time - decalsystem->lastupdatetime);
11494         else
11495                 frametime = 0;
11496         decalsystem->lastupdatetime = cl.time;
11497         decal = decalsystem->decals;
11498         numdecals = decalsystem->numdecals;
11499
11500         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11501         {
11502                 if (decal->color4ub[0][3])
11503                 {
11504                         decal->lived += frametime;
11505                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11506                         {
11507                                 memset(decal, 0, sizeof(*decal));
11508                                 if (decalsystem->freedecal > i)
11509                                         decalsystem->freedecal = i;
11510                         }
11511                 }
11512         }
11513         decal = decalsystem->decals;
11514         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
11515                 numdecals--;
11516
11517         // collapse the array by shuffling the tail decals into the gaps
11518         for (;;)
11519         {
11520                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
11521                         decalsystem->freedecal++;
11522                 if (decalsystem->freedecal == numdecals)
11523                         break;
11524                 decal[decalsystem->freedecal] = decal[--numdecals];
11525         }
11526
11527         decalsystem->numdecals = numdecals;
11528
11529         if (numdecals <= 0)
11530         {
11531                 // if there are no decals left, reset decalsystem
11532                 R_DecalSystem_Reset(decalsystem);
11533         }
11534 }
11535
11536 extern skinframe_t *decalskinframe;
11537 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11538 {
11539         int i;
11540         decalsystem_t *decalsystem = &ent->decalsystem;
11541         int numdecals;
11542         tridecal_t *decal;
11543         float fadedelay;
11544         float faderate;
11545         float alpha;
11546         float *v3f;
11547         float *c4f;
11548         float *t2f;
11549         const int *e;
11550         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11551         int numtris = 0;
11552
11553         numdecals = decalsystem->numdecals;
11554         if (!numdecals)
11555                 return;
11556
11557         if (r_showsurfaces.integer)
11558                 return;
11559
11560         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11561         {
11562                 R_DecalSystem_Reset(decalsystem);
11563                 return;
11564         }
11565
11566         // if the model is static it doesn't matter what value we give for
11567         // wantnormals and wanttangents, so this logic uses only rules applicable
11568         // to a model, knowing that they are meaningless otherwise
11569         if (ent == r_refdef.scene.worldentity)
11570                 RSurf_ActiveWorldEntity();
11571         else
11572                 RSurf_ActiveModelEntity(ent, false, false, false);
11573
11574         decalsystem->lastupdatetime = cl.time;
11575         decal = decalsystem->decals;
11576
11577         fadedelay = cl_decals_time.value;
11578         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11579
11580         // update vertex positions for animated models
11581         v3f = decalsystem->vertex3f;
11582         c4f = decalsystem->color4f;
11583         t2f = decalsystem->texcoord2f;
11584         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11585         {
11586                 if (!decal->color4ub[0][3])
11587                         continue;
11588
11589                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11590                         continue;
11591
11592                 // update color values for fading decals
11593                 if (decal->lived >= cl_decals_time.value)
11594                 {
11595                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11596                         alpha *= (1.0f/255.0f);
11597                 }
11598                 else
11599                         alpha = 1.0f/255.0f;
11600
11601                 c4f[ 0] = decal->color4ub[0][0] * alpha;
11602                 c4f[ 1] = decal->color4ub[0][1] * alpha;
11603                 c4f[ 2] = decal->color4ub[0][2] * alpha;
11604                 c4f[ 3] = 1;
11605                 c4f[ 4] = decal->color4ub[1][0] * alpha;
11606                 c4f[ 5] = decal->color4ub[1][1] * alpha;
11607                 c4f[ 6] = decal->color4ub[1][2] * alpha;
11608                 c4f[ 7] = 1;
11609                 c4f[ 8] = decal->color4ub[2][0] * alpha;
11610                 c4f[ 9] = decal->color4ub[2][1] * alpha;
11611                 c4f[10] = decal->color4ub[2][2] * alpha;
11612                 c4f[11] = 1;
11613
11614                 t2f[0] = decal->texcoord2f[0][0];
11615                 t2f[1] = decal->texcoord2f[0][1];
11616                 t2f[2] = decal->texcoord2f[1][0];
11617                 t2f[3] = decal->texcoord2f[1][1];
11618                 t2f[4] = decal->texcoord2f[2][0];
11619                 t2f[5] = decal->texcoord2f[2][1];
11620
11621                 // update vertex positions for animated models
11622                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
11623                 {
11624                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11625                         VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
11626                         VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
11627                         VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
11628                 }
11629                 else
11630                 {
11631                         VectorCopy(decal->vertex3f[0], v3f);
11632                         VectorCopy(decal->vertex3f[1], v3f + 3);
11633                         VectorCopy(decal->vertex3f[2], v3f + 6);
11634                 }
11635
11636                 v3f += 9;
11637                 c4f += 12;
11638                 t2f += 6;
11639                 numtris++;
11640         }
11641
11642         if (numtris > 0)
11643         {
11644                 r_refdef.stats.drawndecals += numtris;
11645
11646                 if (r_refdef.fogenabled)
11647                 {
11648                         switch(vid.renderpath)
11649                         {
11650                         case RENDERPATH_GL20:
11651                         case RENDERPATH_CGGL:
11652                         case RENDERPATH_GL13:
11653                         case RENDERPATH_GL11:
11654                                 for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
11655                                 {
11656                                         alpha = RSurf_FogVertex(v3f);
11657                                         c4f[0] *= alpha;
11658                                         c4f[1] *= alpha;
11659                                         c4f[2] *= alpha;
11660                                 }
11661                                 break;
11662                         }
11663                 }
11664
11665                 // now render the decals all at once
11666                 // (this assumes they all use one particle font texture!)
11667                 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);
11668                 R_Mesh_ResetTextureState();
11669                 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
11670                 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
11671                 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
11672                 GL_DepthMask(false);
11673                 GL_DepthRange(0, 1);
11674                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11675                 GL_DepthTest(true);
11676                 GL_CullFace(GL_NONE);
11677                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11678                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
11679                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
11680         }
11681 }
11682
11683 static void R_DrawModelDecals(void)
11684 {
11685         int i, numdecals;
11686
11687         // fade faster when there are too many decals
11688         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11689         for (i = 0;i < r_refdef.scene.numentities;i++)
11690                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11691
11692         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11693         for (i = 0;i < r_refdef.scene.numentities;i++)
11694                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11695                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11696
11697         R_DecalSystem_ApplySplatEntitiesQueue();
11698
11699         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11700         for (i = 0;i < r_refdef.scene.numentities;i++)
11701                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11702
11703         r_refdef.stats.totaldecals += numdecals;
11704
11705         if (r_showsurfaces.integer)
11706                 return;
11707
11708         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11709
11710         for (i = 0;i < r_refdef.scene.numentities;i++)
11711         {
11712                 if (!r_refdef.viewcache.entityvisible[i])
11713                         continue;
11714                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11715                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11716         }
11717 }
11718
11719 void R_DrawDebugModel(void)
11720 {
11721         entity_render_t *ent = rsurface.entity;
11722         int i, j, k, l, flagsmask;
11723         const int *elements;
11724         q3mbrush_t *brush;
11725         const msurface_t *surface;
11726         dp_model_t *model = ent->model;
11727         vec3_t v;
11728
11729         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11730
11731         R_Mesh_ColorPointer(NULL, 0, 0);
11732         R_Mesh_ResetTextureState();
11733         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11734         GL_DepthRange(0, 1);
11735         GL_DepthTest(!r_showdisabledepthtest.integer);
11736         GL_DepthMask(false);
11737         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11738
11739         if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
11740         {
11741                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11742                 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
11743                 {
11744                         if (brush->colbrushf && brush->colbrushf->numtriangles)
11745                         {
11746                                 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
11747                                 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);
11748                                 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
11749                         }
11750                 }
11751                 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
11752                 {
11753                         if (surface->num_collisiontriangles)
11754                         {
11755                                 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
11756                                 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);
11757                                 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
11758                         }
11759                 }
11760         }
11761
11762         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11763
11764         if (r_showtris.integer || r_shownormals.integer)
11765         {
11766                 if (r_showdisabledepthtest.integer)
11767                 {
11768                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11769                         GL_DepthMask(false);
11770                 }
11771                 else
11772                 {
11773                         GL_BlendFunc(GL_ONE, GL_ZERO);
11774                         GL_DepthMask(true);
11775                 }
11776                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11777                 {
11778                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11779                                 continue;
11780                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11781                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11782                         {
11783                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
11784                                 if (r_showtris.value > 0)
11785                                 {
11786                                         if (!rsurface.texture->currentlayers->depthmask)
11787                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11788                                         else if (ent == r_refdef.scene.worldentity)
11789                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11790                                         else
11791                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11792                                         elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
11793                                         R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
11794                                         R_Mesh_ColorPointer(NULL, 0, 0);
11795                                         R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
11796                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11797                                         //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
11798                                         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);
11799                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11800                                         CHECKGLERROR
11801                                 }
11802                                 if (r_shownormals.value < 0)
11803                                 {
11804                                         qglBegin(GL_LINES);
11805                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11806                                         {
11807                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11808                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11809                                                 qglVertex3f(v[0], v[1], v[2]);
11810                                                 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
11811                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11812                                                 qglVertex3f(v[0], v[1], v[2]);
11813                                         }
11814                                         qglEnd();
11815                                         CHECKGLERROR
11816                                 }
11817                                 if (r_shownormals.value > 0)
11818                                 {
11819                                         qglBegin(GL_LINES);
11820                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11821                                         {
11822                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11823                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11824                                                 qglVertex3f(v[0], v[1], v[2]);
11825                                                 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
11826                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11827                                                 qglVertex3f(v[0], v[1], v[2]);
11828                                         }
11829                                         qglEnd();
11830                                         CHECKGLERROR
11831                                         qglBegin(GL_LINES);
11832                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11833                                         {
11834                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11835                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11836                                                 qglVertex3f(v[0], v[1], v[2]);
11837                                                 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
11838                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11839                                                 qglVertex3f(v[0], v[1], v[2]);
11840                                         }
11841                                         qglEnd();
11842                                         CHECKGLERROR
11843                                         qglBegin(GL_LINES);
11844                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11845                                         {
11846                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11847                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11848                                                 qglVertex3f(v[0], v[1], v[2]);
11849                                                 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
11850                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11851                                                 qglVertex3f(v[0], v[1], v[2]);
11852                                         }
11853                                         qglEnd();
11854                                         CHECKGLERROR
11855                                 }
11856                         }
11857                 }
11858                 rsurface.texture = NULL;
11859         }
11860 }
11861
11862 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11863 int r_maxsurfacelist = 0;
11864 const msurface_t **r_surfacelist = NULL;
11865 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11866 {
11867         int i, j, endj, f, flagsmask;
11868         texture_t *t;
11869         dp_model_t *model = r_refdef.scene.worldmodel;
11870         msurface_t *surfaces;
11871         unsigned char *update;
11872         int numsurfacelist = 0;
11873         if (model == NULL)
11874                 return;
11875
11876         if (r_maxsurfacelist < model->num_surfaces)
11877         {
11878                 r_maxsurfacelist = model->num_surfaces;
11879                 if (r_surfacelist)
11880                         Mem_Free((msurface_t**)r_surfacelist);
11881                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11882         }
11883
11884         RSurf_ActiveWorldEntity();
11885
11886         surfaces = model->data_surfaces;
11887         update = model->brushq1.lightmapupdateflags;
11888
11889         // update light styles on this submodel
11890         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11891         {
11892                 model_brush_lightstyleinfo_t *style;
11893                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11894                 {
11895                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11896                         {
11897                                 int *list = style->surfacelist;
11898                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11899                                 for (j = 0;j < style->numsurfaces;j++)
11900                                         update[list[j]] = true;
11901                         }
11902                 }
11903         }
11904
11905         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11906
11907         if (debug)
11908         {
11909                 R_DrawDebugModel();
11910                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11911                 return;
11912         }
11913
11914         f = 0;
11915         t = NULL;
11916         rsurface.uselightmaptexture = false;
11917         rsurface.texture = NULL;
11918         rsurface.rtlight = NULL;
11919         numsurfacelist = 0;
11920         // add visible surfaces to draw list
11921         for (i = 0;i < model->nummodelsurfaces;i++)
11922         {
11923                 j = model->sortedmodelsurfaces[i];
11924                 if (r_refdef.viewcache.world_surfacevisible[j])
11925                         r_surfacelist[numsurfacelist++] = surfaces + j;
11926         }
11927         // update lightmaps if needed
11928         if (model->brushq1.firstrender)
11929         {
11930                 model->brushq1.firstrender = false;
11931                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11932                         if (update[j])
11933                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11934         }
11935         else if (update)
11936         {
11937                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11938                         if (r_refdef.viewcache.world_surfacevisible[j])
11939                                 if (update[j])
11940                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11941         }
11942         // don't do anything if there were no surfaces
11943         if (!numsurfacelist)
11944         {
11945                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11946                 return;
11947         }
11948         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11949         GL_AlphaTest(false);
11950
11951         // add to stats if desired
11952         if (r_speeds.integer && !skysurfaces && !depthonly)
11953         {
11954                 r_refdef.stats.world_surfaces += numsurfacelist;
11955                 for (j = 0;j < numsurfacelist;j++)
11956                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11957         }
11958
11959         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11960 }
11961
11962 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11963 {
11964         int i, j, endj, f, flagsmask;
11965         texture_t *t;
11966         dp_model_t *model = ent->model;
11967         msurface_t *surfaces;
11968         unsigned char *update;
11969         int numsurfacelist = 0;
11970         if (model == NULL)
11971                 return;
11972
11973         if (r_maxsurfacelist < model->num_surfaces)
11974         {
11975                 r_maxsurfacelist = model->num_surfaces;
11976                 if (r_surfacelist)
11977                         Mem_Free((msurface_t **)r_surfacelist);
11978                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11979         }
11980
11981         // if the model is static it doesn't matter what value we give for
11982         // wantnormals and wanttangents, so this logic uses only rules applicable
11983         // to a model, knowing that they are meaningless otherwise
11984         if (ent == r_refdef.scene.worldentity)
11985                 RSurf_ActiveWorldEntity();
11986         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11987                 RSurf_ActiveModelEntity(ent, false, false, false);
11988         else if (prepass)
11989                 RSurf_ActiveModelEntity(ent, true, true, true);
11990         else if (depthonly)
11991                 RSurf_ActiveModelEntity(ent, false, false, false);
11992         else
11993         {
11994                 switch (vid.renderpath)
11995                 {
11996                 case RENDERPATH_GL20:
11997                 case RENDERPATH_CGGL:
11998                         RSurf_ActiveModelEntity(ent, true, true, false);
11999                         break;
12000                 case RENDERPATH_GL13:
12001                 case RENDERPATH_GL11:
12002                         RSurf_ActiveModelEntity(ent, true, false, false);
12003                         break;
12004                 }
12005         }
12006
12007         surfaces = model->data_surfaces;
12008         update = model->brushq1.lightmapupdateflags;
12009
12010         // update light styles
12011         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12012         {
12013                 model_brush_lightstyleinfo_t *style;
12014                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12015                 {
12016                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12017                         {
12018                                 int *list = style->surfacelist;
12019                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12020                                 for (j = 0;j < style->numsurfaces;j++)
12021                                         update[list[j]] = true;
12022                         }
12023                 }
12024         }
12025
12026         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12027
12028         if (debug)
12029         {
12030                 R_DrawDebugModel();
12031                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12032                 return;
12033         }
12034
12035         f = 0;
12036         t = NULL;
12037         rsurface.uselightmaptexture = false;
12038         rsurface.texture = NULL;
12039         rsurface.rtlight = NULL;
12040         numsurfacelist = 0;
12041         // add visible surfaces to draw list
12042         for (i = 0;i < model->nummodelsurfaces;i++)
12043                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12044         // don't do anything if there were no surfaces
12045         if (!numsurfacelist)
12046         {
12047                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12048                 return;
12049         }
12050         // update lightmaps if needed
12051         if (update)
12052         {
12053                 int updated = 0;
12054                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12055                 {
12056                         if (update[j])
12057                         {
12058                                 updated++;
12059                                 R_BuildLightMap(ent, surfaces + j);
12060                         }
12061                 }
12062         }
12063         if (update)
12064                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12065                         if (update[j])
12066                                 R_BuildLightMap(ent, surfaces + j);
12067         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12068         GL_AlphaTest(false);
12069
12070         // add to stats if desired
12071         if (r_speeds.integer && !skysurfaces && !depthonly)
12072         {
12073                 r_refdef.stats.entities_surfaces += numsurfacelist;
12074                 for (j = 0;j < numsurfacelist;j++)
12075                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
12076         }
12077
12078         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12079 }
12080
12081 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12082 {
12083         static texture_t texture;
12084         static msurface_t surface;
12085         const msurface_t *surfacelist = &surface;
12086
12087         // fake enough texture and surface state to render this geometry
12088
12089         texture.update_lastrenderframe = -1; // regenerate this texture
12090         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12091         texture.currentskinframe = skinframe;
12092         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12093         texture.specularscalemod = 1;
12094         texture.specularpowermod = 1;
12095
12096         surface.texture = &texture;
12097         surface.num_triangles = numtriangles;
12098         surface.num_firsttriangle = firsttriangle;
12099         surface.num_vertices = numvertices;
12100         surface.num_firstvertex = firstvertex;
12101
12102         // now render it
12103         rsurface.texture = R_GetCurrentTexture(surface.texture);
12104         rsurface.uselightmaptexture = false;
12105         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12106 }
12107
12108 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)
12109 {
12110         static msurface_t surface;
12111         const msurface_t *surfacelist = &surface;
12112
12113         // fake enough texture and surface state to render this geometry
12114
12115         surface.texture = texture;
12116         surface.num_triangles = numtriangles;
12117         surface.num_firsttriangle = firsttriangle;
12118         surface.num_vertices = numvertices;
12119         surface.num_firstvertex = firstvertex;
12120
12121         // now render it
12122         rsurface.texture = R_GetCurrentTexture(surface.texture);
12123         rsurface.uselightmaptexture = false;
12124         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12125 }