]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
fix a typo in FT2 font code
[divverent/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28
29 mempool_t *r_main_mempool;
30 rtexturepool_t *r_main_texturepool;
31
32 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
33
34 static qboolean r_loadnormalmap;
35 static qboolean r_loadgloss;
36 qboolean r_loadfog;
37 static qboolean r_loaddds;
38 static qboolean r_savedds;
39
40 //
41 // screen size info
42 //
43 r_refdef_t r_refdef;
44
45 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
46 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
47 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
48 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
49 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
50 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
51 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
52 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
53
54 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
55 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
56 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
57 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
58 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
59
60 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
61 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
62 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
63 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
64 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
65 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
66 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
67 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
68 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
69 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
70 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
71 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
72 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
73 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
74 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
75 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
76 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
77 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
78 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
79 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
80 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
81 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
82 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
83 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
84 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
85 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
86 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
87 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
88 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
89 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
90 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
91 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
92 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
93 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
94 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
95 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
96 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
97 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
98 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
99 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
100 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
101 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
102
103 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
104 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
105 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
106 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
107 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
108 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
109 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
110 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
111
112 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
113 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
114
115 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
116 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
117 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
118
119 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
120 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
121 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
122 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
123 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
124 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
125 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
126 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
127 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
128
129 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
130 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
131 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
132 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
133 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
134
135 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
136 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
137 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
138 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
139
140 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
141 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
142 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
143 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
144 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
145 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
146 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
147
148 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
149 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
150 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
151 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
152
153 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
154
155 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
156
157 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
158
159 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
160 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
161 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
162 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
163 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
164 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
165 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
166 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "16", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
167
168 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
169
170 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)"};
171
172 extern cvar_t v_glslgamma;
173
174 extern qboolean v_flipped_state;
175
176 static struct r_bloomstate_s
177 {
178         qboolean enabled;
179         qboolean hdr;
180
181         int bloomwidth, bloomheight;
182
183         int screentexturewidth, screentextureheight;
184         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
185
186         int bloomtexturewidth, bloomtextureheight;
187         rtexture_t *texture_bloom;
188
189         // arrays for rendering the screen passes
190         float screentexcoord2f[8];
191         float bloomtexcoord2f[8];
192         float offsettexcoord2f[8];
193
194         r_viewport_t viewport;
195 }
196 r_bloomstate;
197
198 r_waterstate_t r_waterstate;
199
200 /// shadow volume bsp struct with automatically growing nodes buffer
201 svbsp_t r_svbsp;
202
203 rtexture_t *r_texture_blanknormalmap;
204 rtexture_t *r_texture_white;
205 rtexture_t *r_texture_grey128;
206 rtexture_t *r_texture_black;
207 rtexture_t *r_texture_notexture;
208 rtexture_t *r_texture_whitecube;
209 rtexture_t *r_texture_normalizationcube;
210 rtexture_t *r_texture_fogattenuation;
211 rtexture_t *r_texture_gammaramps;
212 unsigned int r_texture_gammaramps_serial;
213 //rtexture_t *r_texture_fogintensity;
214
215 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
216 unsigned int r_numqueries;
217 unsigned int r_maxqueries;
218
219 typedef struct r_qwskincache_s
220 {
221         char name[MAX_QPATH];
222         skinframe_t *skinframe;
223 }
224 r_qwskincache_t;
225
226 static r_qwskincache_t *r_qwskincache;
227 static int r_qwskincache_size;
228
229 /// vertex coordinates for a quad that covers the screen exactly
230 const float r_screenvertex3f[12] =
231 {
232         0, 0, 0,
233         1, 0, 0,
234         1, 1, 0,
235         0, 1, 0
236 };
237
238 extern void R_DrawModelShadows(void);
239
240 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
241 {
242         int i;
243         for (i = 0;i < verts;i++)
244         {
245                 out[0] = in[0] * r;
246                 out[1] = in[1] * g;
247                 out[2] = in[2] * b;
248                 out[3] = in[3];
249                 in += 4;
250                 out += 4;
251         }
252 }
253
254 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
255 {
256         int i;
257         for (i = 0;i < verts;i++)
258         {
259                 out[0] = r;
260                 out[1] = g;
261                 out[2] = b;
262                 out[3] = a;
263                 out += 4;
264         }
265 }
266
267 // FIXME: move this to client?
268 void FOG_clear(void)
269 {
270         if (gamemode == GAME_NEHAHRA)
271         {
272                 Cvar_Set("gl_fogenable", "0");
273                 Cvar_Set("gl_fogdensity", "0.2");
274                 Cvar_Set("gl_fogred", "0.3");
275                 Cvar_Set("gl_foggreen", "0.3");
276                 Cvar_Set("gl_fogblue", "0.3");
277         }
278         r_refdef.fog_density = 0;
279         r_refdef.fog_red = 0;
280         r_refdef.fog_green = 0;
281         r_refdef.fog_blue = 0;
282         r_refdef.fog_alpha = 1;
283         r_refdef.fog_start = 0;
284         r_refdef.fog_end = 16384;
285         r_refdef.fog_height = 1<<30;
286         r_refdef.fog_fadedepth = 128;
287 }
288
289 static void R_BuildBlankTextures(void)
290 {
291         unsigned char data[4];
292         data[2] = 128; // normal X
293         data[1] = 128; // normal Y
294         data[0] = 255; // normal Z
295         data[3] = 128; // height
296         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
297         data[0] = 255;
298         data[1] = 255;
299         data[2] = 255;
300         data[3] = 255;
301         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
302         data[0] = 128;
303         data[1] = 128;
304         data[2] = 128;
305         data[3] = 255;
306         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
307         data[0] = 0;
308         data[1] = 0;
309         data[2] = 0;
310         data[3] = 255;
311         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
312 }
313
314 static void R_BuildNoTexture(void)
315 {
316         int x, y;
317         unsigned char pix[16][16][4];
318         // this makes a light grey/dark grey checkerboard texture
319         for (y = 0;y < 16;y++)
320         {
321                 for (x = 0;x < 16;x++)
322                 {
323                         if ((y < 8) ^ (x < 8))
324                         {
325                                 pix[y][x][0] = 128;
326                                 pix[y][x][1] = 128;
327                                 pix[y][x][2] = 128;
328                                 pix[y][x][3] = 255;
329                         }
330                         else
331                         {
332                                 pix[y][x][0] = 64;
333                                 pix[y][x][1] = 64;
334                                 pix[y][x][2] = 64;
335                                 pix[y][x][3] = 255;
336                         }
337                 }
338         }
339         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
340 }
341
342 static void R_BuildWhiteCube(void)
343 {
344         unsigned char data[6*1*1*4];
345         memset(data, 255, sizeof(data));
346         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
347 }
348
349 static void R_BuildNormalizationCube(void)
350 {
351         int x, y, side;
352         vec3_t v;
353         vec_t s, t, intensity;
354 #define NORMSIZE 64
355         unsigned char *data;
356         data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
357         for (side = 0;side < 6;side++)
358         {
359                 for (y = 0;y < NORMSIZE;y++)
360                 {
361                         for (x = 0;x < NORMSIZE;x++)
362                         {
363                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
364                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
365                                 switch(side)
366                                 {
367                                 default:
368                                 case 0:
369                                         v[0] = 1;
370                                         v[1] = -t;
371                                         v[2] = -s;
372                                         break;
373                                 case 1:
374                                         v[0] = -1;
375                                         v[1] = -t;
376                                         v[2] = s;
377                                         break;
378                                 case 2:
379                                         v[0] = s;
380                                         v[1] = 1;
381                                         v[2] = t;
382                                         break;
383                                 case 3:
384                                         v[0] = s;
385                                         v[1] = -1;
386                                         v[2] = -t;
387                                         break;
388                                 case 4:
389                                         v[0] = s;
390                                         v[1] = -t;
391                                         v[2] = 1;
392                                         break;
393                                 case 5:
394                                         v[0] = -s;
395                                         v[1] = -t;
396                                         v[2] = -1;
397                                         break;
398                                 }
399                                 intensity = 127.0f / sqrt(DotProduct(v, v));
400                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
401                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
402                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
403                                 data[((side*64+y)*64+x)*4+3] = 255;
404                         }
405                 }
406         }
407         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
408         Mem_Free(data);
409 }
410
411 static void R_BuildFogTexture(void)
412 {
413         int x, b;
414 #define FOGWIDTH 256
415         unsigned char data1[FOGWIDTH][4];
416         //unsigned char data2[FOGWIDTH][4];
417         double d, r, alpha;
418
419         r_refdef.fogmasktable_start = r_refdef.fog_start;
420         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
421         r_refdef.fogmasktable_range = r_refdef.fogrange;
422         r_refdef.fogmasktable_density = r_refdef.fog_density;
423
424         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
425         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
426         {
427                 d = (x * r - r_refdef.fogmasktable_start);
428                 if(developer_extra.integer)
429                         Con_DPrintf("%f ", d);
430                 d = max(0, d);
431                 if (r_fog_exp2.integer)
432                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
433                 else
434                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
435                 if(developer_extra.integer)
436                         Con_DPrintf(" : %f ", alpha);
437                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
438                 if(developer_extra.integer)
439                         Con_DPrintf(" = %f\n", alpha);
440                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
441         }
442
443         for (x = 0;x < FOGWIDTH;x++)
444         {
445                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
446                 data1[x][0] = b;
447                 data1[x][1] = b;
448                 data1[x][2] = b;
449                 data1[x][3] = 255;
450                 //data2[x][0] = 255 - b;
451                 //data2[x][1] = 255 - b;
452                 //data2[x][2] = 255 - b;
453                 //data2[x][3] = 255;
454         }
455         if (r_texture_fogattenuation)
456         {
457                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
458                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
459         }
460         else
461         {
462                 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);
463                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
464         }
465 }
466
467 //=======================================================================================================================================================
468
469 static const char *builtinshaderstring =
470 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
471 "// written by Forest 'LordHavoc' Hale\n"
472 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
473 "\n"
474 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
475 "# define USEFOG\n"
476 "#endif\n"
477 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
478 "#define USELIGHTMAP\n"
479 "#endif\n"
480 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING)\n"
481 "#define USEEYEVECTOR\n"
482 "#endif\n"
483 "\n"
484 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
485 "# extension GL_ARB_texture_rectangle : enable\n"
486 "#endif\n"
487 "\n"
488 "#ifdef USESHADOWMAP2D\n"
489 "# ifdef GL_EXT_gpu_shader4\n"
490 "#   extension GL_EXT_gpu_shader4 : enable\n"
491 "# endif\n"
492 "# ifdef GL_ARB_texture_gather\n"
493 "#   extension GL_ARB_texture_gather : enable\n"
494 "# else\n"
495 "#   ifdef GL_AMD_texture_texture4\n"
496 "#     extension GL_AMD_texture_texture4 : enable\n"
497 "#   endif\n"
498 "# endif\n"
499 "#endif\n"
500 "\n"
501 "#ifdef USESHADOWMAPCUBE\n"
502 "# extension GL_EXT_gpu_shader4 : enable\n"
503 "#endif\n"
504 "\n"
505 "//#ifdef USESHADOWSAMPLER\n"
506 "//# extension GL_ARB_shadow : enable\n"
507 "//#endif\n"
508 "\n"
509 "//#ifdef __GLSL_CG_DATA_TYPES\n"
510 "//# define myhalf half\n"
511 "//# define myhalf2 half2\n"
512 "//# define myhalf3 half3\n"
513 "//# define myhalf4 half4\n"
514 "//#else\n"
515 "# define myhalf float\n"
516 "# define myhalf2 vec2\n"
517 "# define myhalf3 vec3\n"
518 "# define myhalf4 vec4\n"
519 "//#endif\n"
520 "\n"
521 "#ifdef VERTEX_SHADER\n"
522 "uniform mat4 ModelViewProjectionMatrix;\n"
523 "#endif\n"
524 "\n"
525 "#ifdef MODE_DEPTH_OR_SHADOW\n"
526 "#ifdef VERTEX_SHADER\n"
527 "void main(void)\n"
528 "{\n"
529 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
530 "}\n"
531 "#endif\n"
532 "#else // !MODE_DEPTH_ORSHADOW\n"
533 "\n"
534 "\n"
535 "\n"
536 "\n"
537 "#ifdef MODE_SHOWDEPTH\n"
538 "#ifdef VERTEX_SHADER\n"
539 "void main(void)\n"
540 "{\n"
541 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
542 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
543 "}\n"
544 "#endif\n"
545 "\n"
546 "#ifdef FRAGMENT_SHADER\n"
547 "void main(void)\n"
548 "{\n"
549 "       gl_FragColor = gl_Color;\n"
550 "}\n"
551 "#endif\n"
552 "#else // !MODE_SHOWDEPTH\n"
553 "\n"
554 "\n"
555 "\n"
556 "\n"
557 "#ifdef MODE_POSTPROCESS\n"
558 "varying vec2 TexCoord1;\n"
559 "varying vec2 TexCoord2;\n"
560 "\n"
561 "#ifdef VERTEX_SHADER\n"
562 "void main(void)\n"
563 "{\n"
564 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
565 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
566 "#ifdef USEBLOOM\n"
567 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
568 "#endif\n"
569 "}\n"
570 "#endif\n"
571 "\n"
572 "#ifdef FRAGMENT_SHADER\n"
573 "uniform sampler2D Texture_First;\n"
574 "#ifdef USEBLOOM\n"
575 "uniform sampler2D Texture_Second;\n"
576 "#endif\n"
577 "#ifdef USEGAMMARAMPS\n"
578 "uniform sampler2D Texture_GammaRamps;\n"
579 "#endif\n"
580 "#ifdef USESATURATION\n"
581 "uniform float Saturation;\n"
582 "#endif\n"
583 "#ifdef USEVIEWTINT\n"
584 "uniform vec4 ViewTintColor;\n"
585 "#endif\n"
586 "//uncomment these if you want to use them:\n"
587 "uniform vec4 UserVec1;\n"
588 "// uniform vec4 UserVec2;\n"
589 "// uniform vec4 UserVec3;\n"
590 "// uniform vec4 UserVec4;\n"
591 "// uniform float ClientTime;\n"
592 "uniform vec2 PixelSize;\n"
593 "void main(void)\n"
594 "{\n"
595 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
596 "#ifdef USEBLOOM\n"
597 "       gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
598 "#endif\n"
599 "#ifdef USEVIEWTINT\n"
600 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
601 "#endif\n"
602 "\n"
603 "#ifdef USEPOSTPROCESSING\n"
604 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
605 "// 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"
606 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
607 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
608 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
609 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
610 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
611 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
612 "#endif\n"
613 "\n"
614 "#ifdef USESATURATION\n"
615 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
616 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
617 "       //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
618 "       gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
619 "#endif\n"
620 "\n"
621 "#ifdef USEGAMMARAMPS\n"
622 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
623 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
624 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
625 "#endif\n"
626 "}\n"
627 "#endif\n"
628 "#else // !MODE_POSTPROCESS\n"
629 "\n"
630 "\n"
631 "\n"
632 "\n"
633 "#ifdef MODE_GENERIC\n"
634 "#ifdef USEDIFFUSE\n"
635 "varying vec2 TexCoord1;\n"
636 "#endif\n"
637 "#ifdef USESPECULAR\n"
638 "varying vec2 TexCoord2;\n"
639 "#endif\n"
640 "#ifdef VERTEX_SHADER\n"
641 "void main(void)\n"
642 "{\n"
643 "       gl_FrontColor = gl_Color;\n"
644 "#ifdef USEDIFFUSE\n"
645 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
646 "#endif\n"
647 "#ifdef USESPECULAR\n"
648 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
649 "#endif\n"
650 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
651 "}\n"
652 "#endif\n"
653 "\n"
654 "#ifdef FRAGMENT_SHADER\n"
655 "#ifdef USEDIFFUSE\n"
656 "uniform sampler2D Texture_First;\n"
657 "#endif\n"
658 "#ifdef USESPECULAR\n"
659 "uniform sampler2D Texture_Second;\n"
660 "#endif\n"
661 "\n"
662 "void main(void)\n"
663 "{\n"
664 "       gl_FragColor = gl_Color;\n"
665 "#ifdef USEDIFFUSE\n"
666 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
667 "#endif\n"
668 "\n"
669 "#ifdef USESPECULAR\n"
670 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
671 "# ifdef USECOLORMAPPING\n"
672 "       gl_FragColor *= tex2;\n"
673 "# endif\n"
674 "# ifdef USEGLOW\n"
675 "       gl_FragColor += tex2;\n"
676 "# endif\n"
677 "# ifdef USEVERTEXTEXTUREBLEND\n"
678 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
679 "# endif\n"
680 "#endif\n"
681 "}\n"
682 "#endif\n"
683 "#else // !MODE_GENERIC\n"
684 "\n"
685 "\n"
686 "\n"
687 "\n"
688 "#ifdef MODE_BLOOMBLUR\n"
689 "varying TexCoord;\n"
690 "#ifdef VERTEX_SHADER\n"
691 "void main(void)\n"
692 "{\n"
693 "       gl_FrontColor = gl_Color;\n"
694 "       TexCoord = gl_MultiTexCoord0.xy;\n"
695 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
696 "}\n"
697 "#endif\n"
698 "\n"
699 "#ifdef FRAGMENT_SHADER\n"
700 "uniform sampler2D Texture_First;\n"
701 "uniform vec4 BloomBlur_Parameters;\n"
702 "\n"
703 "void main(void)\n"
704 "{\n"
705 "       int i;\n"
706 "       vec2 tc = TexCoord;\n"
707 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
708 "       tc += BloomBlur_Parameters.xy;\n"
709 "       for (i = 1;i < SAMPLES;i++)\n"
710 "       {\n"
711 "               color += texture2D(Texture_First, tc).rgb;\n"
712 "               tc += BloomBlur_Parameters.xy;\n"
713 "       }\n"
714 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
715 "}\n"
716 "#endif\n"
717 "#else // !MODE_BLOOMBLUR\n"
718 "#ifdef MODE_REFRACTION\n"
719 "varying vec2 TexCoord;\n"
720 "varying vec4 ModelViewProjectionPosition;\n"
721 "uniform mat4 TexMatrix;\n"
722 "#ifdef VERTEX_SHADER\n"
723 "\n"
724 "void main(void)\n"
725 "{\n"
726 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
727 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
728 "       ModelViewProjectionPosition = gl_Position;\n"
729 "}\n"
730 "#endif\n"
731 "\n"
732 "#ifdef FRAGMENT_SHADER\n"
733 "uniform sampler2D Texture_Normal;\n"
734 "uniform sampler2D Texture_Refraction;\n"
735 "uniform sampler2D Texture_Reflection;\n"
736 "\n"
737 "uniform vec4 DistortScaleRefractReflect;\n"
738 "uniform vec4 ScreenScaleRefractReflect;\n"
739 "uniform vec4 ScreenCenterRefractReflect;\n"
740 "uniform vec4 RefractColor;\n"
741 "uniform vec4 ReflectColor;\n"
742 "uniform float ReflectFactor;\n"
743 "uniform float ReflectOffset;\n"
744 "\n"
745 "void main(void)\n"
746 "{\n"
747 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
748 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
749 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
750 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
751 "       // FIXME temporary hack to detect the case that the reflection\n"
752 "       // gets blackened at edges due to leaving the area that contains actual\n"
753 "       // content.\n"
754 "       // Remove this 'ack once we have a better way to stop this thing from\n"
755 "       // 'appening.\n"
756 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
757 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
758 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
759 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
760 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
761 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
762 "}\n"
763 "#endif\n"
764 "#else // !MODE_REFRACTION\n"
765 "\n"
766 "\n"
767 "\n"
768 "\n"
769 "#ifdef MODE_WATER\n"
770 "varying vec2 TexCoord;\n"
771 "varying vec3 EyeVector;\n"
772 "varying vec4 ModelViewProjectionPosition;\n"
773 "#ifdef VERTEX_SHADER\n"
774 "uniform vec3 EyePosition;\n"
775 "uniform mat4 TexMatrix;\n"
776 "\n"
777 "void main(void)\n"
778 "{\n"
779 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
780 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
781 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
782 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
783 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
784 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
785 "       ModelViewProjectionPosition = gl_Position;\n"
786 "}\n"
787 "#endif\n"
788 "\n"
789 "#ifdef FRAGMENT_SHADER\n"
790 "uniform sampler2D Texture_Normal;\n"
791 "uniform sampler2D Texture_Refraction;\n"
792 "uniform sampler2D Texture_Reflection;\n"
793 "\n"
794 "uniform vec4 DistortScaleRefractReflect;\n"
795 "uniform vec4 ScreenScaleRefractReflect;\n"
796 "uniform vec4 ScreenCenterRefractReflect;\n"
797 "uniform vec4 RefractColor;\n"
798 "uniform vec4 ReflectColor;\n"
799 "uniform float ReflectFactor;\n"
800 "uniform float ReflectOffset;\n"
801 "\n"
802 "void main(void)\n"
803 "{\n"
804 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
805 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
806 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
807 "       vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
808 "       // FIXME temporary hack to detect the case that the reflection\n"
809 "       // gets blackened at edges due to leaving the area that contains actual\n"
810 "       // content.\n"
811 "       // Remove this 'ack once we have a better way to stop this thing from\n"
812 "       // 'appening.\n"
813 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
814 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
815 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
816 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
817 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
818 "       f       = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
819 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
820 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
821 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
822 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
823 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
824 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
825 "}\n"
826 "#endif\n"
827 "#else // !MODE_WATER\n"
828 "\n"
829 "\n"
830 "\n"
831 "\n"
832 "// common definitions between vertex shader and fragment shader:\n"
833 "\n"
834 "varying vec2 TexCoord;\n"
835 "#ifdef USEVERTEXTEXTUREBLEND\n"
836 "varying vec2 TexCoord2;\n"
837 "#endif\n"
838 "#ifdef USELIGHTMAP\n"
839 "varying vec2 TexCoordLightmap;\n"
840 "#endif\n"
841 "\n"
842 "#ifdef MODE_LIGHTSOURCE\n"
843 "varying vec3 CubeVector;\n"
844 "#endif\n"
845 "\n"
846 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
847 "varying vec3 LightVector;\n"
848 "#endif\n"
849 "\n"
850 "#ifdef USEEYEVECTOR\n"
851 "varying vec3 EyeVector;\n"
852 "#endif\n"
853 "#ifdef USEFOG\n"
854 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
855 "#endif\n"
856 "\n"
857 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
858 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
859 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
860 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
861 "#endif\n"
862 "\n"
863 "#ifdef USEREFLECTION\n"
864 "varying vec4 ModelViewProjectionPosition;\n"
865 "#endif\n"
866 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
867 "uniform vec3 LightPosition;\n"
868 "varying vec4 ModelViewPosition;\n"
869 "#endif\n"
870 "\n"
871 "#ifdef MODE_LIGHTSOURCE\n"
872 "uniform vec3 LightPosition;\n"
873 "#endif\n"
874 "uniform vec3 EyePosition;\n"
875 "#ifdef MODE_LIGHTDIRECTION\n"
876 "uniform vec3 LightDir;\n"
877 "#endif\n"
878 "uniform vec4 FogPlane;\n"
879 "\n"
880 "\n"
881 "\n"
882 "\n"
883 "\n"
884 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
885 "\n"
886 "// fragment shader specific:\n"
887 "#ifdef FRAGMENT_SHADER\n"
888 "\n"
889 "uniform sampler2D Texture_Normal;\n"
890 "uniform sampler2D Texture_Color;\n"
891 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
892 "uniform sampler2D Texture_Gloss;\n"
893 "//#endif\n"
894 "#ifdef USEGLOW\n"
895 "uniform sampler2D Texture_Glow;\n"
896 "#endif\n"
897 "#ifdef USEVERTEXTEXTUREBLEND\n"
898 "uniform sampler2D Texture_SecondaryNormal;\n"
899 "uniform sampler2D Texture_SecondaryColor;\n"
900 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
901 "uniform sampler2D Texture_SecondaryGloss;\n"
902 "//#endif\n"
903 "#ifdef USEGLOW\n"
904 "uniform sampler2D Texture_SecondaryGlow;\n"
905 "#endif\n"
906 "#endif\n"
907 "#ifdef USECOLORMAPPING\n"
908 "uniform sampler2D Texture_Pants;\n"
909 "uniform sampler2D Texture_Shirt;\n"
910 "#endif\n"
911 "#ifdef USEFOG\n"
912 "uniform sampler2D Texture_FogMask;\n"
913 "#endif\n"
914 "#ifdef USELIGHTMAP\n"
915 "uniform sampler2D Texture_Lightmap;\n"
916 "#endif\n"
917 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
918 "uniform sampler2D Texture_Deluxemap;\n"
919 "#endif\n"
920 "#ifdef USEREFLECTION\n"
921 "uniform sampler2D Texture_Reflection;\n"
922 "#endif\n"
923 "\n"
924 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
925 "uniform sampler2D Texture_ScreenDepth;\n"
926 "uniform sampler2D Texture_ScreenNormalMap;\n"
927 "#endif\n"
928 "#ifdef USEDEFERREDLIGHTMAP\n"
929 "uniform sampler2D Texture_ScreenDiffuse;\n"
930 "uniform sampler2D Texture_ScreenSpecular;\n"
931 "#endif\n"
932 "\n"
933 "uniform myhalf3 Color_Pants;\n"
934 "uniform myhalf3 Color_Shirt;\n"
935 "uniform myhalf3 FogColor;\n"
936 "\n"
937 "#ifdef USEFOG\n"
938 "uniform float FogRangeRecip;\n"
939 "uniform float FogPlaneViewDist;\n"
940 "uniform float FogHeightFade;\n"
941 "float FogVertex(void)\n"
942 "{\n"
943 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
944 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
945 "       float fogfrac;\n"
946 "#ifdef USEFOGOUTSIDE\n"
947 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
948 "#else\n"
949 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
950 "#endif\n"
951 "       return float(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
952 "}\n"
953 "#endif\n"
954 "\n"
955 "#ifdef USEOFFSETMAPPING\n"
956 "uniform float OffsetMapping_Scale;\n"
957 "vec2 OffsetMapping(vec2 TexCoord)\n"
958 "{\n"
959 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
960 "       // 14 sample relief mapping: linear search and then binary search\n"
961 "       // this basically steps forward a small amount repeatedly until it finds\n"
962 "       // itself inside solid, then jitters forward and back using decreasing\n"
963 "       // amounts to find the impact\n"
964 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
965 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
966 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
967 "       vec3 RT = vec3(TexCoord, 1);\n"
968 "       OffsetVector *= 0.1;\n"
969 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
970 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
971 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
972 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
973 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
974 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
975 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
976 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
977 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
978 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
979 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
980 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
981 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
982 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
983 "       return RT.xy;\n"
984 "#else\n"
985 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
986 "       // this basically moves forward the full distance, and then backs up based\n"
987 "       // on height of samples\n"
988 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
989 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
990 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
991 "       TexCoord += OffsetVector;\n"
992 "       OffsetVector *= 0.333;\n"
993 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
994 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
995 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
996 "       return TexCoord;\n"
997 "#endif\n"
998 "}\n"
999 "#endif // USEOFFSETMAPPING\n"
1000 "\n"
1001 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1002 "uniform sampler2D Texture_Attenuation;\n"
1003 "uniform samplerCube Texture_Cube;\n"
1004 "\n"
1005 "#ifdef USESHADOWMAPRECT\n"
1006 "# ifdef USESHADOWSAMPLER\n"
1007 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1008 "# else\n"
1009 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1010 "# endif\n"
1011 "#endif\n"
1012 "\n"
1013 "#ifdef USESHADOWMAP2D\n"
1014 "# ifdef USESHADOWSAMPLER\n"
1015 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1016 "# else\n"
1017 "uniform sampler2D Texture_ShadowMap2D;\n"
1018 "# endif\n"
1019 "#endif\n"
1020 "\n"
1021 "#ifdef USESHADOWMAPVSDCT\n"
1022 "uniform samplerCube Texture_CubeProjection;\n"
1023 "#endif\n"
1024 "\n"
1025 "#ifdef USESHADOWMAPCUBE\n"
1026 "# ifdef USESHADOWSAMPLER\n"
1027 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1028 "# else\n"
1029 "uniform samplerCube Texture_ShadowMapCube;\n"
1030 "# endif\n"
1031 "#endif\n"
1032 "\n"
1033 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1034 "uniform vec2 ShadowMap_TextureScale;\n"
1035 "uniform vec4 ShadowMap_Parameters;\n"
1036 "#endif\n"
1037 "\n"
1038 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1039 "# ifndef USESHADOWMAPVSDCT\n"
1040 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1041 "{\n"
1042 "       vec3 adir = abs(dir);\n"
1043 "       vec2 tc;\n"
1044 "       vec2 offset;\n"
1045 "       float ma;\n"
1046 "       if (adir.x > adir.y)\n"
1047 "       {\n"
1048 "               if (adir.x > adir.z) // X\n"
1049 "               {\n"
1050 "                       ma = adir.x;\n"
1051 "                       tc = dir.zy;\n"
1052 "                       offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
1053 "               }\n"
1054 "               else // Z\n"
1055 "               {\n"
1056 "                       ma = adir.z;\n"
1057 "                       tc = dir.xy;\n"
1058 "                       offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1059 "               }\n"
1060 "       }\n"
1061 "       else\n"
1062 "       {\n"
1063 "               if (adir.y > adir.z) // Y\n"
1064 "               {\n"
1065 "                       ma = adir.y;\n"
1066 "                       tc = dir.xz;\n"
1067 "                       offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
1068 "               }\n"
1069 "               else // Z\n"
1070 "               {\n"
1071 "                       ma = adir.z;\n"
1072 "                       tc = dir.xy;\n"
1073 "                       offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1074 "               }\n"
1075 "       }\n"
1076 "\n"
1077 "       vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1078 "       stc.xy += offset * ShadowMap_Parameters.y;\n"
1079 "       stc.z += ShadowMap_Parameters.z;\n"
1080 "       return stc;\n"
1081 "}\n"
1082 "# else\n"
1083 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1084 "{\n"
1085 "       vec3 adir = abs(dir);\n"
1086 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1087 "       float ma = max(max(adir.x, adir.y), adir.z);\n"
1088 "       vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1089 "       stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
1090 "       stc.z += ShadowMap_Parameters.z;\n"
1091 "       return stc;\n"
1092 "}\n"
1093 "# endif\n"
1094 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1095 "\n"
1096 "#ifdef USESHADOWMAPCUBE\n"
1097 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1098 "{\n"
1099 "       vec3 adir = abs(dir);\n"
1100 "       return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1101 "}\n"
1102 "#endif\n"
1103 "\n"
1104 "# ifdef USESHADOWMAPRECT\n"
1105 "float ShadowMapCompare(vec3 dir)\n"
1106 "{\n"
1107 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1108 "       float f;\n"
1109 "#  ifdef USESHADOWSAMPLER\n"
1110 "\n"
1111 "#    ifdef USESHADOWMAPPCF\n"
1112 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1113 "       f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1114 "#    else\n"
1115 "       f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1116 "#    endif\n"
1117 "\n"
1118 "#  else\n"
1119 "\n"
1120 "#    ifdef USESHADOWMAPPCF\n"
1121 "#      if USESHADOWMAPPCF > 1\n"
1122 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1123 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1124 "       vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1125 "       vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
1126 "       vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
1127 "       vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
1128 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1129 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1130 "#      else\n"
1131 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1132 "       vec2 offset = fract(shadowmaptc.xy);\n"
1133 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1134 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1135 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1136 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1137 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1138 "#      endif\n"
1139 "#    else\n"
1140 "       f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1141 "#    endif\n"
1142 "\n"
1143 "#  endif\n"
1144 "       return f;\n"
1145 "}\n"
1146 "# endif\n"
1147 "\n"
1148 "# ifdef USESHADOWMAP2D\n"
1149 "float ShadowMapCompare(vec3 dir)\n"
1150 "{\n"
1151 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1152 "       float f;\n"
1153 "\n"
1154 "#  ifdef USESHADOWSAMPLER\n"
1155 "#    ifdef USESHADOWMAPPCF\n"
1156 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1157 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1158 "       f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1159 "#    else\n"
1160 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1161 "#    endif\n"
1162 "#  else\n"
1163 "#    ifdef USESHADOWMAPPCF\n"
1164 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1165 "#      ifdef GL_ARB_texture_gather\n"
1166 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1167 "#      else\n"
1168 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1169 "#      endif\n"
1170 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1171 "       center *= ShadowMap_TextureScale;\n"
1172 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1173 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1174 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1175 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1176 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1177 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1178 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1179 "#     else\n"
1180 "#      ifdef GL_EXT_gpu_shader4\n"
1181 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1182 "#      else\n"
1183 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1184 "#      endif\n"
1185 "#      if USESHADOWMAPPCF > 1\n"
1186 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1187 "       center *= ShadowMap_TextureScale;\n"
1188 "       vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1189 "       vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
1190 "       vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
1191 "       vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
1192 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1193 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1194 "#      else\n"
1195 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1196 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1197 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1198 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1199 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1200 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1201 "#      endif\n"
1202 "#     endif\n"
1203 "#    else\n"
1204 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1205 "#    endif\n"
1206 "#  endif\n"
1207 "       return f;\n"
1208 "}\n"
1209 "# endif\n"
1210 "\n"
1211 "# ifdef USESHADOWMAPCUBE\n"
1212 "float ShadowMapCompare(vec3 dir)\n"
1213 "{\n"
1214 "       // apply depth texture cubemap as light filter\n"
1215 "       vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1216 "       float f;\n"
1217 "#  ifdef USESHADOWSAMPLER\n"
1218 "       f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1219 "#  else\n"
1220 "       f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1221 "#  endif\n"
1222 "       return f;\n"
1223 "}\n"
1224 "# endif\n"
1225 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
1226 "#endif // FRAGMENT_SHADER\n"
1227 "\n"
1228 "\n"
1229 "\n"
1230 "\n"
1231 "#ifdef MODE_DEFERREDGEOMETRY\n"
1232 "#ifdef VERTEX_SHADER\n"
1233 "uniform mat4 TexMatrix;\n"
1234 "#ifdef USEVERTEXTEXTUREBLEND\n"
1235 "uniform mat4 BackgroundTexMatrix;\n"
1236 "#endif\n"
1237 "uniform mat4 ModelViewMatrix;\n"
1238 "void main(void)\n"
1239 "{\n"
1240 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1241 "#ifdef USEVERTEXTEXTUREBLEND\n"
1242 "       gl_FrontColor = gl_Color;\n"
1243 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1244 "#endif\n"
1245 "\n"
1246 "       // transform unnormalized eye direction into tangent space\n"
1247 "#ifdef USEOFFSETMAPPING\n"
1248 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1249 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1250 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1251 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1252 "#endif\n"
1253 "\n"
1254 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1255 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1256 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1257 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1258 "}\n"
1259 "#endif // VERTEX_SHADER\n"
1260 "\n"
1261 "#ifdef FRAGMENT_SHADER\n"
1262 "void main(void)\n"
1263 "{\n"
1264 "#ifdef USEOFFSETMAPPING\n"
1265 "       // apply offsetmapping\n"
1266 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1267 "#define TexCoord TexCoordOffset\n"
1268 "#endif\n"
1269 "\n"
1270 "#ifdef USEALPHAKILL\n"
1271 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1272 "               discard;\n"
1273 "#endif\n"
1274 "\n"
1275 "#ifdef USEVERTEXTEXTUREBLEND\n"
1276 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1277 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1278 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1279 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1280 "#endif\n"
1281 "\n"
1282 "#ifdef USEVERTEXTEXTUREBLEND\n"
1283 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1284 "#else\n"
1285 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1286 "#endif\n"
1287 "\n"
1288 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), 1);\n"
1289 "}\n"
1290 "#endif // FRAGMENT_SHADER\n"
1291 "#else // !MODE_DEFERREDGEOMETRY\n"
1292 "\n"
1293 "\n"
1294 "\n"
1295 "\n"
1296 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1297 "#ifdef VERTEX_SHADER\n"
1298 "uniform mat4 ModelViewMatrix;\n"
1299 "void main(void)\n"
1300 "{\n"
1301 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1302 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1303 "}\n"
1304 "#endif // VERTEX_SHADER\n"
1305 "\n"
1306 "#ifdef FRAGMENT_SHADER\n"
1307 "uniform mat4 ViewToLight;\n"
1308 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1309 "uniform vec2 ScreenToDepth;\n"
1310 "uniform myhalf3 DeferredColor_Ambient;\n"
1311 "uniform myhalf3 DeferredColor_Diffuse;\n"
1312 "#ifdef USESPECULAR\n"
1313 "uniform myhalf3 DeferredColor_Specular;\n"
1314 "uniform myhalf SpecularPower;\n"
1315 "#endif\n"
1316 "uniform myhalf2 PixelToScreenTexCoord;\n"
1317 "void main(void)\n"
1318 "{\n"
1319 "       // calculate viewspace pixel position\n"
1320 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1321 "       vec3 position;\n"
1322 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1323 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1324 "       // decode viewspace pixel normal\n"
1325 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1326 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1327 "       // surfacenormal = pixel normal in viewspace\n"
1328 "       // LightVector = pixel to light in viewspace\n"
1329 "       // CubeVector = position in lightspace\n"
1330 "       // eyevector = pixel to view in viewspace\n"
1331 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1332 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1333 "#ifdef USEDIFFUSE\n"
1334 "       // calculate diffuse shading\n"
1335 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1336 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1337 "#endif\n"
1338 "#ifdef USESPECULAR\n"
1339 "       // calculate directional shading\n"
1340 "       vec3 eyevector = position * -1.0;\n"
1341 "#  ifdef USEEXACTSPECULARMATH\n"
1342 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
1343 "#  else\n"
1344 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1345 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1346 "#  endif\n"
1347 "#endif\n"
1348 "\n"
1349 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1350 "       fade *= ShadowMapCompare(CubeVector);\n"
1351 "#endif\n"
1352 "\n"
1353 "#ifdef USEDIFFUSE\n"
1354 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1355 "#else\n"
1356 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1357 "#endif\n"
1358 "#ifdef USESPECULAR\n"
1359 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1360 "#else\n"
1361 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1362 "#endif\n"
1363 "\n"
1364 "# ifdef USECUBEFILTER\n"
1365 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1366 "       gl_FragData[0].rgb *= cubecolor;\n"
1367 "       gl_FragData[1].rgb *= cubecolor;\n"
1368 "# endif\n"
1369 "}\n"
1370 "#endif // FRAGMENT_SHADER\n"
1371 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1372 "\n"
1373 "\n"
1374 "\n"
1375 "\n"
1376 "#ifdef VERTEX_SHADER\n"
1377 "uniform mat4 TexMatrix;\n"
1378 "#ifdef USEVERTEXTEXTUREBLEND\n"
1379 "uniform mat4 BackgroundTexMatrix;\n"
1380 "#endif\n"
1381 "#ifdef MODE_LIGHTSOURCE\n"
1382 "uniform mat4 ModelToLight;\n"
1383 "#endif\n"
1384 "void main(void)\n"
1385 "{\n"
1386 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1387 "       gl_FrontColor = gl_Color;\n"
1388 "#endif\n"
1389 "       // copy the surface texcoord\n"
1390 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1391 "#ifdef USEVERTEXTEXTUREBLEND\n"
1392 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1393 "#endif\n"
1394 "#ifdef USELIGHTMAP\n"
1395 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1396 "#endif\n"
1397 "\n"
1398 "#ifdef MODE_LIGHTSOURCE\n"
1399 "       // transform vertex position into light attenuation/cubemap space\n"
1400 "       // (-1 to +1 across the light box)\n"
1401 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1402 "\n"
1403 "# ifdef USEDIFFUSE\n"
1404 "       // transform unnormalized light direction into tangent space\n"
1405 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1406 "       //  normalize it per pixel)\n"
1407 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1408 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1409 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1410 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1411 "# endif\n"
1412 "#endif\n"
1413 "\n"
1414 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1415 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1416 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1417 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1418 "#endif\n"
1419 "\n"
1420 "       // transform unnormalized eye direction into tangent space\n"
1421 "#ifdef USEEYEVECTOR\n"
1422 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1423 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1424 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1425 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1426 "#endif\n"
1427 "\n"
1428 "#ifdef USEFOG\n"
1429 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1430 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1431 "#endif\n"
1432 "\n"
1433 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1434 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1435 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1436 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1437 "#endif\n"
1438 "\n"
1439 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1440 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1441 "\n"
1442 "#ifdef USEREFLECTION\n"
1443 "       ModelViewProjectionPosition = gl_Position;\n"
1444 "#endif\n"
1445 "}\n"
1446 "#endif // VERTEX_SHADER\n"
1447 "\n"
1448 "\n"
1449 "\n"
1450 "\n"
1451 "#ifdef FRAGMENT_SHADER\n"
1452 "#ifdef USEDEFERREDLIGHTMAP\n"
1453 "uniform myhalf2 PixelToScreenTexCoord;\n"
1454 "uniform myhalf3 DeferredMod_Diffuse;\n"
1455 "uniform myhalf3 DeferredMod_Specular;\n"
1456 "#endif\n"
1457 "uniform myhalf3 Color_Ambient;\n"
1458 "uniform myhalf3 Color_Diffuse;\n"
1459 "uniform myhalf3 Color_Specular;\n"
1460 "uniform myhalf SpecularPower;\n"
1461 "#ifdef USEGLOW\n"
1462 "uniform myhalf3 Color_Glow;\n"
1463 "#endif\n"
1464 "uniform myhalf Alpha;\n"
1465 "#ifdef USEREFLECTION\n"
1466 "uniform vec4 DistortScaleRefractReflect;\n"
1467 "uniform vec4 ScreenScaleRefractReflect;\n"
1468 "uniform vec4 ScreenCenterRefractReflect;\n"
1469 "uniform myhalf4 ReflectColor;\n"
1470 "#endif\n"
1471 "#ifdef MODE_LIGHTDIRECTION\n"
1472 "uniform myhalf3 LightColor;\n"
1473 "#endif\n"
1474 "#ifdef MODE_LIGHTSOURCE\n"
1475 "uniform myhalf3 LightColor;\n"
1476 "#endif\n"
1477 "void main(void)\n"
1478 "{\n"
1479 "#ifdef USEOFFSETMAPPING\n"
1480 "       // apply offsetmapping\n"
1481 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1482 "#define TexCoord TexCoordOffset\n"
1483 "#endif\n"
1484 "\n"
1485 "       // combine the diffuse textures (base, pants, shirt)\n"
1486 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1487 "#ifdef USEALPHAKILL\n"
1488 "       if (color.a < 0.5)\n"
1489 "               discard;\n"
1490 "#endif\n"
1491 "       color.a *= Alpha;\n"
1492 "#ifdef USECOLORMAPPING\n"
1493 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1494 "#endif\n"
1495 "#ifdef USEVERTEXTEXTUREBLEND\n"
1496 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1497 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1498 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1499 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1500 "       color.a = 1.0;\n"
1501 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1502 "#endif\n"
1503 "\n"
1504 "       // get the surface normal\n"
1505 "#ifdef USEVERTEXTEXTUREBLEND\n"
1506 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1507 "#else\n"
1508 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1509 "#endif\n"
1510 "\n"
1511 "       // get the material colors\n"
1512 "       myhalf3 diffusetex = color.rgb;\n"
1513 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1514 "# ifdef USEVERTEXTEXTUREBLEND\n"
1515 "       myhalf3 glosstex = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1516 "# else\n"
1517 "       myhalf3 glosstex = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1518 "# endif\n"
1519 "#endif\n"
1520 "\n"
1521 "\n"
1522 "\n"
1523 "\n"
1524 "#ifdef MODE_LIGHTSOURCE\n"
1525 "       // light source\n"
1526 "#ifdef USEDIFFUSE\n"
1527 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1528 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1529 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1530 "#ifdef USESPECULAR\n"
1531 "#ifdef USEEXACTSPECULARMATH\n"
1532 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1533 "#else\n"
1534 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1535 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1536 "#endif\n"
1537 "       color.rgb += glosstex * (specular * Color_Specular);\n"
1538 "#endif\n"
1539 "#else\n"
1540 "       color.rgb = diffusetex * Color_Ambient;\n"
1541 "#endif\n"
1542 "       color.rgb *= LightColor;\n"
1543 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1544 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1545 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1546 "#endif\n"
1547 "# ifdef USECUBEFILTER\n"
1548 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1549 "# endif\n"
1550 "#endif // MODE_LIGHTSOURCE\n"
1551 "\n"
1552 "\n"
1553 "\n"
1554 "\n"
1555 "#ifdef MODE_LIGHTDIRECTION\n"
1556 "#define SHADING\n"
1557 "#ifdef USEDIFFUSE\n"
1558 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1559 "#endif\n"
1560 "#define lightcolor LightColor\n"
1561 "#endif // MODE_LIGHTDIRECTION\n"
1562 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1563 "#define SHADING\n"
1564 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1565 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1566 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1567 "       // convert modelspace light vector to tangentspace\n"
1568 "       myhalf3 lightnormal;\n"
1569 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1570 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1571 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1572 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1573 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1574 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1575 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1576 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1577 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1578 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1579 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1580 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1581 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1582 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1583 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1584 "#define SHADING\n"
1585 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1586 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1587 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1588 "#endif\n"
1589 "\n"
1590 "\n"
1591 "\n"
1592 "\n"
1593 "#ifdef MODE_LIGHTMAP\n"
1594 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1595 "#endif // MODE_LIGHTMAP\n"
1596 "#ifdef MODE_VERTEXCOLOR\n"
1597 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1598 "#endif // MODE_VERTEXCOLOR\n"
1599 "#ifdef MODE_FLATCOLOR\n"
1600 "       color.rgb = diffusetex * Color_Ambient;\n"
1601 "#endif // MODE_FLATCOLOR\n"
1602 "\n"
1603 "\n"
1604 "\n"
1605 "\n"
1606 "#ifdef SHADING\n"
1607 "# ifdef USEDIFFUSE\n"
1608 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1609 "#  ifdef USESPECULAR\n"
1610 "#   ifdef USEEXACTSPECULARMATH\n"
1611 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1612 "#   else\n"
1613 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1614 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1615 "#   endif\n"
1616 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
1617 "#  else\n"
1618 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1619 "#  endif\n"
1620 "# else\n"
1621 "       color.rgb = diffusetex * Color_Ambient;\n"
1622 "# endif\n"
1623 "#endif\n"
1624 "\n"
1625 "#ifdef USEDEFERREDLIGHTMAP\n"
1626 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1627 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1628 "       color.rgb += glosstex * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1629 "#endif\n"
1630 "\n"
1631 "#ifdef USEGLOW\n"
1632 "#ifdef USEVERTEXTEXTUREBLEND\n"
1633 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1634 "#else\n"
1635 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1636 "#endif\n"
1637 "#endif\n"
1638 "\n"
1639 "#ifdef USEFOG\n"
1640 "#ifdef MODE_LIGHTSOURCE\n"
1641 "       color.rgb *= myhalf(FogVertex());\n"
1642 "#else\n"
1643 "       color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1644 "#endif\n"
1645 "#endif\n"
1646 "\n"
1647 "       // 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"
1648 "#ifdef USEREFLECTION\n"
1649 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1650 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1651 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1652 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1653 "       // FIXME temporary hack to detect the case that the reflection\n"
1654 "       // gets blackened at edges due to leaving the area that contains actual\n"
1655 "       // content.\n"
1656 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1657 "       // 'appening.\n"
1658 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1659 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1660 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1661 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1662 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1663 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1664 "#endif\n"
1665 "\n"
1666 "       gl_FragColor = vec4(color);\n"
1667 "}\n"
1668 "#endif // FRAGMENT_SHADER\n"
1669 "\n"
1670 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1671 "#endif // !MODE_DEFERREDGEOMETRY\n"
1672 "#endif // !MODE_WATER\n"
1673 "#endif // !MODE_REFRACTION\n"
1674 "#endif // !MODE_BLOOMBLUR\n"
1675 "#endif // !MODE_GENERIC\n"
1676 "#endif // !MODE_POSTPROCESS\n"
1677 "#endif // !MODE_SHOWDEPTH\n"
1678 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1679 ;
1680
1681 /*
1682 =========================================================================================================================================================
1683
1684
1685
1686 =========================================================================================================================================================
1687
1688
1689
1690 =========================================================================================================================================================
1691
1692
1693
1694 =========================================================================================================================================================
1695
1696
1697
1698 =========================================================================================================================================================
1699
1700
1701
1702 =========================================================================================================================================================
1703
1704
1705
1706 =========================================================================================================================================================
1707 */
1708
1709 const char *builtincgshaderstring =
1710 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1711 "// written by Forest 'LordHavoc' Hale\n"
1712 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1713 "\n"
1714 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
1715 "# define USEFOG\n"
1716 "#endif\n"
1717 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1718 "#define USELIGHTMAP\n"
1719 "#endif\n"
1720 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING)\n"
1721 "#define USEEYEVECTOR\n"
1722 "#endif\n"
1723 "\n"
1724 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1725 "#ifdef VERTEX_SHADER\n"
1726 "void main\n"
1727 "(\n"
1728 "float4 gl_Vertex : POSITION,\n"
1729 "uniform float4x4 ModelViewProjectionMatrix,\n"
1730 "out float4 gl_Position : POSITION\n"
1731 ")\n"
1732 "{\n"
1733 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1734 "}\n"
1735 "#endif\n"
1736 "#else // !MODE_DEPTH_ORSHADOW\n"
1737 "\n"
1738 "\n"
1739 "\n"
1740 "\n"
1741 "#ifdef MODE_SHOWDEPTH\n"
1742 "#ifdef VERTEX_SHADER\n"
1743 "void main\n"
1744 "(\n"
1745 "float4 gl_Vertex : POSITION,\n"
1746 "uniform float4x4 ModelViewProjectionMatrix,\n"
1747 "out float4 gl_Position : POSITION,\n"
1748 "out float4 gl_FrontColor : COLOR0\n"
1749 ")\n"
1750 "{\n"
1751 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1752 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1753 "}\n"
1754 "#endif\n"
1755 "\n"
1756 "#ifdef FRAGMENT_SHADER\n"
1757 "void main\n"
1758 "(\n"
1759 "float4 gl_FrontColor : COLOR0,\n"
1760 "out float4 gl_FragColor : COLOR\n"
1761 ")\n"
1762 "{\n"
1763 "       gl_FragColor = gl_FrontColor;\n"
1764 "}\n"
1765 "#endif\n"
1766 "#else // !MODE_SHOWDEPTH\n"
1767 "\n"
1768 "\n"
1769 "\n"
1770 "\n"
1771 "#ifdef MODE_POSTPROCESS\n"
1772 "\n"
1773 "#ifdef VERTEX_SHADER\n"
1774 "void main\n"
1775 "(\n"
1776 "float4 gl_Vertex : POSITION,\n"
1777 "uniform float4x4 ModelViewProjectionMatrix,\n"
1778 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1779 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1780 "out float4 gl_Position : POSITION,\n"
1781 "out float2 TexCoord1 : TEXCOORD0,\n"
1782 "out float2 TexCoord2 : TEXCOORD1\n"
1783 ")\n"
1784 "{\n"
1785 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1786 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1787 "#ifdef USEBLOOM\n"
1788 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1789 "#endif\n"
1790 "}\n"
1791 "#endif\n"
1792 "\n"
1793 "#ifdef FRAGMENT_SHADER\n"
1794 "void main\n"
1795 "(\n"
1796 "float2 TexCoord1 : TEXCOORD0,\n"
1797 "float2 TexCoord2 : TEXCOORD1,\n"
1798 "uniform sampler2D Texture_First,\n"
1799 "#ifdef USEBLOOM\n"
1800 "uniform sampler2D Texture_Second,\n"
1801 "#endif\n"
1802 "#ifdef USEGAMMARAMPS\n"
1803 "uniform sampler2D Texture_GammaRamps,\n"
1804 "#endif\n"
1805 "#ifdef USESATURATION\n"
1806 "uniform float Saturation,\n"
1807 "#endif\n"
1808 "#ifdef USEVIEWTINT\n"
1809 "uniform float4 ViewTintColor,\n"
1810 "#endif\n"
1811 "uniform float4 UserVec1,\n"
1812 "uniform float4 UserVec2,\n"
1813 "uniform float4 UserVec3,\n"
1814 "uniform float4 UserVec4,\n"
1815 "uniform float ClientTime,\n"
1816 "uniform float2 PixelSize,\n"
1817 "out float4 gl_FragColor : COLOR\n"
1818 ")\n"
1819 "{\n"
1820 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1821 "#ifdef USEBLOOM\n"
1822 "       gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
1823 "#endif\n"
1824 "#ifdef USEVIEWTINT\n"
1825 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1826 "#endif\n"
1827 "\n"
1828 "#ifdef USEPOSTPROCESSING\n"
1829 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1830 "// 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"
1831 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1832 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1833 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1834 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
1835 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
1836 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
1837 "#endif\n"
1838 "\n"
1839 "#ifdef USESATURATION\n"
1840 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
1841 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
1842 "       //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
1843 "       gl_FragColor.rgb = lerp(float3(y), gl_FragColor.rgb, Saturation);\n"
1844 "#endif\n"
1845 "\n"
1846 "#ifdef USEGAMMARAMPS\n"
1847 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
1848 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
1849 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
1850 "#endif\n"
1851 "}\n"
1852 "#endif\n"
1853 "#else // !MODE_POSTPROCESS\n"
1854 "\n"
1855 "\n"
1856 "\n"
1857 "\n"
1858 "#ifdef MODE_GENERIC\n"
1859 "#ifdef VERTEX_SHADER\n"
1860 "void main\n"
1861 "(\n"
1862 "float4 gl_Vertex : POSITION,\n"
1863 "uniform float4x4 ModelViewProjectionMatrix,\n"
1864 "float4 gl_Color : COLOR0,\n"
1865 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1866 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1867 "out float4 gl_Position : POSITION,\n"
1868 "out float4 gl_FrontColor : COLOR,\n"
1869 "out float2 TexCoord1 : TEXCOORD0,\n"
1870 "out float2 TexCoord2 : TEXCOORD1\n"
1871 ")\n"
1872 "{\n"
1873 "       gl_FrontColor = gl_Color;\n"
1874 "#ifdef USEDIFFUSE\n"
1875 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1876 "#endif\n"
1877 "#ifdef USESPECULAR\n"
1878 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1879 "#endif\n"
1880 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1881 "}\n"
1882 "#endif\n"
1883 "\n"
1884 "#ifdef FRAGMENT_SHADER\n"
1885 "\n"
1886 "void main\n"
1887 "(\n"
1888 "float4 gl_FrontColor : COLOR,\n"
1889 "float2 TexCoord1 : TEXCOORD0,\n"
1890 "float2 TexCoord2 : TEXCOORD1,\n"
1891 "#ifdef USEDIFFUSE\n"
1892 "uniform sampler2D Texture_First,\n"
1893 "#endif\n"
1894 "#ifdef USESPECULAR\n"
1895 "uniform sampler2D Texture_Second,\n"
1896 "#endif\n"
1897 "out float4 gl_FragColor : COLOR\n"
1898 ")\n"
1899 "{\n"
1900 "       gl_FragColor = gl_FrontColor;\n"
1901 "#ifdef USEDIFFUSE\n"
1902 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
1903 "#endif\n"
1904 "\n"
1905 "#ifdef USESPECULAR\n"
1906 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
1907 "# ifdef USECOLORMAPPING\n"
1908 "       gl_FragColor *= tex2;\n"
1909 "# endif\n"
1910 "# ifdef USEGLOW\n"
1911 "       gl_FragColor += tex2;\n"
1912 "# endif\n"
1913 "# ifdef USEVERTEXTEXTUREBLEND\n"
1914 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
1915 "# endif\n"
1916 "#endif\n"
1917 "}\n"
1918 "#endif\n"
1919 "#else // !MODE_GENERIC\n"
1920 "\n"
1921 "\n"
1922 "\n"
1923 "\n"
1924 "#ifdef MODE_BLOOMBLUR\n"
1925 "#ifdef VERTEX_SHADER\n"
1926 "void main\n"
1927 "(\n"
1928 "float4 gl_Vertex : POSITION,\n"
1929 "uniform float4x4 ModelViewProjectionMatrix,\n"
1930 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1931 "out float4 gl_Position : POSITION,\n"
1932 "out float2 TexCoord : TEXCOORD0\n"
1933 ")\n"
1934 "{\n"
1935 "       TexCoord = gl_MultiTexCoord0.xy;\n"
1936 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1937 "}\n"
1938 "#endif\n"
1939 "\n"
1940 "#ifdef FRAGMENT_SHADER\n"
1941 "\n"
1942 "void main\n"
1943 "(\n"
1944 "float2 TexCoord : TEXCOORD0,\n"
1945 "uniform sampler2D Texture_First,\n"
1946 "uniform float4 BloomBlur_Parameters,\n"
1947 "out float4 gl_FragColor : COLOR\n"
1948 ")\n"
1949 "{\n"
1950 "       int i;\n"
1951 "       float2 tc = TexCoord;\n"
1952 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
1953 "       tc += BloomBlur_Parameters.xy;\n"
1954 "       for (i = 1;i < SAMPLES;i++)\n"
1955 "       {\n"
1956 "               color += tex2D(Texture_First, tc).rgb;\n"
1957 "               tc += BloomBlur_Parameters.xy;\n"
1958 "       }\n"
1959 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
1960 "}\n"
1961 "#endif\n"
1962 "#else // !MODE_BLOOMBLUR\n"
1963 "#ifdef MODE_REFRACTION\n"
1964 "#ifdef VERTEX_SHADER\n"
1965 "void main\n"
1966 "(\n"
1967 "float4 gl_Vertex : POSITION,\n"
1968 "uniform float4x4 ModelViewProjectionMatrix,\n"
1969 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1970 "uniform float4x4 TexMatrix,\n"
1971 "uniform float3 EyePosition,\n"
1972 "out float4 gl_Position : POSITION,\n"
1973 "out float2 TexCoord : TEXCOORD0,\n"
1974 "out float3 EyeVector : TEXCOORD1,\n"
1975 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
1976 ")\n"
1977 "{\n"
1978 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
1979 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1980 "       ModelViewProjectionPosition = gl_Position;\n"
1981 "}\n"
1982 "#endif\n"
1983 "\n"
1984 "#ifdef FRAGMENT_SHADER\n"
1985 "void main\n"
1986 "(\n"
1987 "float2 TexCoord : TEXCOORD0,\n"
1988 "float3 EyeVector : TEXCOORD1,\n"
1989 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
1990 "uniform sampler2D Texture_Normal,\n"
1991 "uniform sampler2D Texture_Refraction,\n"
1992 "uniform sampler2D Texture_Reflection,\n"
1993 "uniform float4 DistortScaleRefractReflect,\n"
1994 "uniform float4 ScreenScaleRefractReflect,\n"
1995 "uniform float4 ScreenCenterRefractReflect,\n"
1996 "uniform float4 RefractColor,\n"
1997 "out float4 gl_FragColor : COLOR\n"
1998 ")\n"
1999 "{\n"
2000 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2001 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2002 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2003 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
2004 "       // FIXME temporary hack to detect the case that the reflection\n"
2005 "       // gets blackened at edges due to leaving the area that contains actual\n"
2006 "       // content.\n"
2007 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2008 "       // 'appening.\n"
2009 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2010 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2011 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2012 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2013 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2014 "       gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2015 "}\n"
2016 "#endif\n"
2017 "#else // !MODE_REFRACTION\n"
2018 "\n"
2019 "\n"
2020 "\n"
2021 "\n"
2022 "#ifdef MODE_WATER\n"
2023 "#ifdef VERTEX_SHADER\n"
2024 "\n"
2025 "void main\n"
2026 "(\n"
2027 "float4 gl_Vertex : POSITION,\n"
2028 "uniform float4x4 ModelViewProjectionMatrix,\n"
2029 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2030 "uniform float4x4 TexMatrix,\n"
2031 "uniform float3 EyePosition,\n"
2032 "out float4 gl_Position : POSITION,\n"
2033 "out float2 TexCoord : TEXCOORD0,\n"
2034 "out float3 EyeVector : TEXCOORD1,\n"
2035 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2036 ")\n"
2037 "{\n"
2038 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2039 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2040 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2041 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2042 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2043 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2044 "       ModelViewProjectionPosition = gl_Position;\n"
2045 "}\n"
2046 "#endif\n"
2047 "\n"
2048 "#ifdef FRAGMENT_SHADER\n"
2049 "void main\n"
2050 "(\n"
2051 "float2 TexCoord : TEXCOORD0,\n"
2052 "float3 EyeVector : TEXCOORD1,\n"
2053 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2054 "uniform sampler2D Texture_Normal,\n"
2055 "uniform sampler2D Texture_Refraction,\n"
2056 "uniform sampler2D Texture_Reflection,\n"
2057 "uniform float4 DistortScaleRefractReflect,\n"
2058 "uniform float4 ScreenScaleRefractReflect,\n"
2059 "uniform float4 ScreenCenterRefractReflect,\n"
2060 "uniform float4 RefractColor,\n"
2061 "uniform float4 ReflectColor,\n"
2062 "uniform float ReflectFactor,\n"
2063 "uniform float ReflectOffset,\n"
2064 "out float4 gl_FragColor : COLOR\n"
2065 ")\n"
2066 "{\n"
2067 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2068 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2069 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2070 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xyxy * DistortScaleRefractReflect;\n"
2071 "       // FIXME temporary hack to detect the case that the reflection\n"
2072 "       // gets blackened at edges due to leaving the area that contains actual\n"
2073 "       // content.\n"
2074 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2075 "       // 'appening.\n"
2076 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2077 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2078 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2079 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2080 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2081 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2082 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2083 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2084 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2085 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2086 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2087 "       gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2088 "}\n"
2089 "#endif\n"
2090 "#else // !MODE_WATER\n"
2091 "\n"
2092 "\n"
2093 "\n"
2094 "\n"
2095 "// 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"
2096 "\n"
2097 "// fragment shader specific:\n"
2098 "#ifdef FRAGMENT_SHADER\n"
2099 "\n"
2100 "#ifdef USEFOG\n"
2101 "float FogVertex(float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask)\n"
2102 "{\n"
2103 "       float fogfrac;\n"
2104 "#ifdef USEFOGOUTSIDE\n"
2105 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2106 "#else\n"
2107 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2108 "#endif\n"
2109 "       return float(tex2D(Texture_FogMask, half2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
2110 "}\n"
2111 "#endif\n"
2112 "\n"
2113 "#ifdef USEOFFSETMAPPING\n"
2114 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler2D Texture_Normal)\n"
2115 "{\n"
2116 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2117 "       // 14 sample relief mapping: linear search and then binary search\n"
2118 "       // this basically steps forward a small amount repeatedly until it finds\n"
2119 "       // itself inside solid, then jitters forward and back using decreasing\n"
2120 "       // amounts to find the impact\n"
2121 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2122 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2123 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2124 "       float3 RT = float3(TexCoord, 1);\n"
2125 "       OffsetVector *= 0.1;\n"
2126 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2127 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2128 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2129 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2130 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2131 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2132 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2133 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2134 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2135 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2136 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2137 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2138 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2139 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2140 "       return RT.xy;\n"
2141 "#else\n"
2142 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2143 "       // this basically moves forward the full distance, and then backs up based\n"
2144 "       // on height of samples\n"
2145 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2146 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2147 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2148 "       TexCoord += OffsetVector;\n"
2149 "       OffsetVector *= 0.333;\n"
2150 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2151 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2152 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2153 "       return TexCoord;\n"
2154 "#endif\n"
2155 "}\n"
2156 "#endif // USEOFFSETMAPPING\n"
2157 "\n"
2158 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2159 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2160 "# ifndef USESHADOWMAPVSDCT\n"
2161 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2162 "{\n"
2163 "       float3 adir = abs(dir);\n"
2164 "       float2 tc;\n"
2165 "       float2 offset;\n"
2166 "       float ma;\n"
2167 "       if (adir.x > adir.y)\n"
2168 "       {\n"
2169 "               if (adir.x > adir.z) // X\n"
2170 "               {\n"
2171 "                       ma = adir.x;\n"
2172 "                       tc = dir.zy;\n"
2173 "                       offset = float2(lerp(0.5, 1.5, dir.x < 0.0), 0.5);\n"
2174 "               }\n"
2175 "               else // Z\n"
2176 "               {\n"
2177 "                       ma = adir.z;\n"
2178 "                       tc = dir.xy;\n"
2179 "                       offset = float2(lerp(0.5, 1.5, dir.z < 0.0), 2.5);\n"
2180 "               }\n"
2181 "       }\n"
2182 "       else\n"
2183 "       {\n"
2184 "               if (adir.y > adir.z) // Y\n"
2185 "               {\n"
2186 "                       ma = adir.y;\n"
2187 "                       tc = dir.xz;\n"
2188 "                       offset = float2(lerp(0.5, 1.5, dir.y < 0.0), 1.5);\n"
2189 "               }\n"
2190 "               else // Z\n"
2191 "               {\n"
2192 "                       ma = adir.z;\n"
2193 "                       tc = dir.xy;\n"
2194 "                       offset = float2(lerp(0.5, 1.5, dir.z < 0.0), 2.5);\n"
2195 "               }\n"
2196 "       }\n"
2197 "\n"
2198 "       float3 stc = float3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2199 "       stc.xy += offset * ShadowMap_Parameters.y;\n"
2200 "       stc.z += ShadowMap_Parameters.z;\n"
2201 "       return stc;\n"
2202 "}\n"
2203 "# else\n"
2204 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2205 "{\n"
2206 "       float3 adir = abs(dir);\n"
2207 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2208 "       float ma = max(max(adir.x, adir.y), adir.z);\n"
2209 "       float3 stc = float3(lerp(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2210 "       stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
2211 "       stc.z += ShadowMap_Parameters.z;\n"
2212 "       return stc;\n"
2213 "}\n"
2214 "# endif\n"
2215 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2216 "\n"
2217 "#ifdef USESHADOWMAPCUBE\n"
2218 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2219 "{\n"
2220 "    float3 adir = abs(dir);\n"
2221 "    return float4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
2222 "}\n"
2223 "#endif\n"
2224 "\n"
2225 "# ifdef USESHADOWMAPRECT\n"
2226 "#ifdef USESHADOWMAPVSDCT\n"
2227 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2228 "#else\n"
2229 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2230 "#endif\n"
2231 "{\n"
2232 "#ifdef USESHADOWMAPVSDCT\n"
2233 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2234 "#else\n"
2235 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2236 "#endif\n"
2237 "       float f;\n"
2238 "#  ifdef USESHADOWSAMPLER\n"
2239 "\n"
2240 "#    ifdef USESHADOWMAPPCF\n"
2241 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2242 "    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"
2243 "#    else\n"
2244 "    f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2245 "#    endif\n"
2246 "\n"
2247 "#  else\n"
2248 "\n"
2249 "#    ifdef USESHADOWMAPPCF\n"
2250 "#      if USESHADOWMAPPCF > 1\n"
2251 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2252 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2253 "    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"
2254 "    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"
2255 "    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"
2256 "    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"
2257 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2258 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2259 "#      else\n"
2260 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2261 "    float2 offset = frac(shadowmaptc.xy);\n"
2262 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2263 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2264 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2265 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2266 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2267 "#      endif\n"
2268 "#    else\n"
2269 "    f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2270 "#    endif\n"
2271 "\n"
2272 "#  endif\n"
2273 "       return f;\n"
2274 "}\n"
2275 "# endif\n"
2276 "\n"
2277 "# ifdef USESHADOWMAP2D\n"
2278 "#ifdef USESHADOWMAPVSDCT\n"
2279 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2280 "#else\n"
2281 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2282 "#endif\n"
2283 "{\n"
2284 "#ifdef USESHADOWMAPVSDCT\n"
2285 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2286 "#else\n"
2287 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2288 "#endif\n"
2289 "    float f;\n"
2290 "\n"
2291 "#  ifdef USESHADOWSAMPLER\n"
2292 "#    ifdef USESHADOWMAPPCF\n"
2293 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, float3(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
2294 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2295 "    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"
2296 "#    else\n"
2297 "    f = shadow2D(Texture_ShadowMap2D, float3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
2298 "#    endif\n"
2299 "#  else\n"
2300 "#    ifdef USESHADOWMAPPCF\n"
2301 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2302 "#      ifdef GL_ARB_texture_gather\n"
2303 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
2304 "#      else\n"
2305 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x,y)*ShadowMap_TextureScale)\n"
2306 "#      endif\n"
2307 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2308 "    center *= ShadowMap_TextureScale;\n"
2309 "    float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2310 "    float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2311 "    float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2312 "    float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2313 "    float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2314 "                lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2315 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2316 "#     else\n"
2317 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)  \n"
2318 "#      if USESHADOWMAPPCF > 1\n"
2319 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2320 "    center *= ShadowMap_TextureScale;\n"
2321 "    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"
2322 "    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"
2323 "    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"
2324 "    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"
2325 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2326 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2327 "#      else\n"
2328 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2329 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2330 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2331 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2332 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2333 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2334 "#      endif\n"
2335 "#     endif\n"
2336 "#    else\n"
2337 "    f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2338 "#    endif\n"
2339 "#  endif\n"
2340 "    return f;\n"
2341 "}\n"
2342 "# endif\n"
2343 "\n"
2344 "# ifdef USESHADOWMAPCUBE\n"
2345 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2346 "{\n"
2347 "    // apply depth texture cubemap as light filter\n"
2348 "    float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2349 "    float f;\n"
2350 "#  ifdef USESHADOWSAMPLER\n"
2351 "    f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2352 "#  else\n"
2353 "    f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2354 "#  endif\n"
2355 "    return f;\n"
2356 "}\n"
2357 "# endif\n"
2358 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2359 "#endif // FRAGMENT_SHADER\n"
2360 "\n"
2361 "\n"
2362 "\n"
2363 "\n"
2364 "#ifdef MODE_DEFERREDGEOMETRY\n"
2365 "#ifdef VERTEX_SHADER\n"
2366 "void main\n"
2367 "(\n"
2368 "float4 gl_Vertex : POSITION,\n"
2369 "uniform float4x4 ModelViewProjectionMatrix,\n"
2370 "#ifdef USEVERTEXTEXTUREBLEND\n"
2371 "float4 gl_Color : COLOR0,\n"
2372 "#endif\n"
2373 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2374 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2375 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2376 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2377 "uniform float4x4 TexMatrix,\n"
2378 "#ifdef USEVERTEXTEXTUREBLEND\n"
2379 "uniform float4x4 BackgroundTexMatrix,\n"
2380 "#endif\n"
2381 "uniform float4x4 ModelViewMatrix,\n"
2382 "#ifdef USEOFFSETMAPPING\n"
2383 "uniform float3 EyePosition,\n"
2384 "#endif\n"
2385 "out float4 gl_Position : POSITION,\n"
2386 "out float4 gl_FrontColor : COLOR,\n"
2387 "out float4 TexCoordBoth : TEXCOORD0,\n"
2388 "#ifdef USEOFFSETMAPPING\n"
2389 "out float3 EyeVector : TEXCOORD2,\n"
2390 "#endif\n"
2391 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2392 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2393 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2394 ")\n"
2395 "{\n"
2396 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2397 "#ifdef USEVERTEXTEXTUREBLEND\n"
2398 "       gl_FrontColor = gl_Color;\n"
2399 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2400 "#endif\n"
2401 "\n"
2402 "       // transform unnormalized eye direction into tangent space\n"
2403 "#ifdef USEOFFSETMAPPING\n"
2404 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2405 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2406 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2407 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2408 "#endif\n"
2409 "\n"
2410 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2411 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2412 "       VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2413 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2414 "}\n"
2415 "#endif // VERTEX_SHADER\n"
2416 "\n"
2417 "#ifdef FRAGMENT_SHADER\n"
2418 "void main\n"
2419 "(\n"
2420 "float4 TexCoordBoth : TEXCOORD0,\n"
2421 "float3 EyeVector : TEXCOORD2,\n"
2422 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2423 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2424 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2425 "uniform sampler2D Texture_Normal,\n"
2426 "#ifdef USEALPHAKILL\n"
2427 "uniform sampler2D Texture_Color,\n"
2428 "#endif\n"
2429 "#ifdef USEVERTEXTEXTUREBLEND\n"
2430 "uniform sampler2D Texture_SecondaryNormal,\n"
2431 "#endif\n"
2432 "#ifdef USEOFFSETMAPPING\n"
2433 "uniform float OffsetMapping_Scale,\n"
2434 "#endif\n"
2435 "uniform half SpecularPower,\n"
2436 "out float4 gl_FragColor : COLOR\n"
2437 ")\n"
2438 "{\n"
2439 "       float2 TexCoord = TexCoordBoth.xy;\n"
2440 "#ifdef USEOFFSETMAPPING\n"
2441 "       // apply offsetmapping\n"
2442 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2443 "#define TexCoord TexCoordOffset\n"
2444 "#endif\n"
2445 "\n"
2446 "#ifdef USEALPHAKILL\n"
2447 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2448 "               discard;\n"
2449 "#endif\n"
2450 "\n"
2451 "#ifdef USEVERTEXTEXTUREBLEND\n"
2452 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2453 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2454 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2455 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2456 "#endif\n"
2457 "\n"
2458 "#ifdef USEVERTEXTEXTUREBLEND\n"
2459 "       float3 surfacenormal = lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
2460 "#else\n"
2461 "       float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
2462 "#endif\n"
2463 "\n"
2464 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), 1);\n"
2465 "}\n"
2466 "#endif // FRAGMENT_SHADER\n"
2467 "#else // !MODE_DEFERREDGEOMETRY\n"
2468 "\n"
2469 "\n"
2470 "\n"
2471 "\n"
2472 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2473 "#ifdef VERTEX_SHADER\n"
2474 "void main\n"
2475 "(\n"
2476 "float4 gl_Vertex : POSITION,\n"
2477 "uniform float4x4 ModelViewProjectionMatrix,\n"
2478 "uniform float4x4 ModelViewMatrix,\n"
2479 "out float4 gl_Position : POSITION,\n"
2480 "out float4 ModelViewPosition : TEXCOORD0\n"
2481 ")\n"
2482 "{\n"
2483 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2484 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2485 "}\n"
2486 "#endif // VERTEX_SHADER\n"
2487 "\n"
2488 "#ifdef FRAGMENT_SHADER\n"
2489 "void main\n"
2490 "(\n"
2491 "float2 Pixel : WPOS,\n"
2492 "float4 ModelViewPosition : TEXCOORD0,\n"
2493 "uniform float4x4 ViewToLight,\n"
2494 "uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2495 "uniform float3 LightPosition,\n"
2496 "uniform half2 PixelToScreenTexCoord,\n"
2497 "uniform half3 DeferredColor_Ambient,\n"
2498 "uniform half3 DeferredColor_Diffuse,\n"
2499 "#ifdef USESPECULAR\n"
2500 "uniform half3 DeferredColor_Specular,\n"
2501 "uniform half SpecularPower,\n"
2502 "#endif\n"
2503 "uniform sampler2D Texture_Attenuation,\n"
2504 "uniform sampler2D Texture_ScreenDepth,\n"
2505 "uniform sampler2D Texture_ScreenNormalMap,\n"
2506 "\n"
2507 "#ifdef USESHADOWMAPRECT\n"
2508 "# ifdef USESHADOWSAMPLER\n"
2509 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2510 "# else\n"
2511 "uniform samplerRECT Texture_ShadowMapRect,\n"
2512 "# endif\n"
2513 "#endif\n"
2514 "\n"
2515 "#ifdef USESHADOWMAP2D\n"
2516 "# ifdef USESHADOWSAMPLER\n"
2517 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2518 "# else\n"
2519 "uniform sampler2D Texture_ShadowMap2D,\n"
2520 "# endif\n"
2521 "#endif\n"
2522 "\n"
2523 "#ifdef USESHADOWMAPVSDCT\n"
2524 "uniform samplerCUBE Texture_CubeProjection,\n"
2525 "#endif\n"
2526 "\n"
2527 "#ifdef USESHADOWMAPCUBE\n"
2528 "# ifdef USESHADOWSAMPLER\n"
2529 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2530 "# else\n"
2531 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2532 "# endif\n"
2533 "#endif\n"
2534 "\n"
2535 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2536 "uniform float2 ShadowMap_TextureScale,\n"
2537 "uniform float4 ShadowMap_Parameters,\n"
2538 "#endif\n"
2539 "\n"
2540 "out float4 gl_FragData0 : COLOR0,\n"
2541 "out float4 gl_FragData1 : COLOR1\n"
2542 ")\n"
2543 "{\n"
2544 "       // calculate viewspace pixel position\n"
2545 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2546 "       ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2547 "       float3 position;\n"
2548 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2549 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2550 "       // decode viewspace pixel normal\n"
2551 "       half4 normalmap = tex2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
2552 "       half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
2553 "       // surfacenormal = pixel normal in viewspace\n"
2554 "       // LightVector = pixel to light in viewspace\n"
2555 "       // CubeVector = position in lightspace\n"
2556 "       // eyevector = pixel to view in viewspace\n"
2557 "       float3 CubeVector = float3(mul(ViewToLight, float4(position,1)));\n"
2558 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2559 "#ifdef USEDIFFUSE\n"
2560 "       // calculate diffuse shading\n"
2561 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2562 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2563 "#endif\n"
2564 "#ifdef USESPECULAR\n"
2565 "       // calculate directional shading\n"
2566 "       float3 eyevector = position * -1.0;\n"
2567 "#  ifdef USEEXACTSPECULARMATH\n"
2568 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
2569 "#  else\n"
2570 "       half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
2571 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
2572 "#  endif\n"
2573 "#endif\n"
2574 "\n"
2575 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2576 "       fade *= ShadowMapCompare(CubeVector,\n"
2577 "# if defined(USESHADOWMAP2D)\n"
2578 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2579 "# endif\n"
2580 "# if defined(USESHADOWMAPRECT)\n"
2581 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2582 "# endif\n"
2583 "# if defined(USESHADOWMAPCUBE)\n"
2584 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2585 "# endif\n"
2586 "\n"
2587 "#ifdef USESHADOWMAPVSDCT\n"
2588 ", Texture_CubeProjection\n"
2589 "#endif\n"
2590 "       );\n"
2591 "#endif\n"
2592 "\n"
2593 "#ifdef USEDIFFUSE\n"
2594 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2595 "#else\n"
2596 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2597 "#endif\n"
2598 "#ifdef USESPECULAR\n"
2599 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2600 "#else\n"
2601 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2602 "#endif\n"
2603 "\n"
2604 "# ifdef USECUBEFILTER\n"
2605 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2606 "       gl_FragData0.rgb *= cubecolor;\n"
2607 "       gl_FragData1.rgb *= cubecolor;\n"
2608 "# endif\n"
2609 "}\n"
2610 "#endif // FRAGMENT_SHADER\n"
2611 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2612 "\n"
2613 "\n"
2614 "\n"
2615 "\n"
2616 "#ifdef VERTEX_SHADER\n"
2617 "void main\n"
2618 "(\n"
2619 "float4 gl_Vertex : POSITION,\n"
2620 "uniform float4x4 ModelViewProjectionMatrix,\n"
2621 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2622 "float4 gl_Color : COLOR0,\n"
2623 "#endif\n"
2624 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2625 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2626 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2627 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2628 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2629 "\n"
2630 "uniform float3 EyePosition,\n"
2631 "uniform float4x4 TexMatrix,\n"
2632 "#ifdef USEVERTEXTEXTUREBLEND\n"
2633 "uniform float4x4 BackgroundTexMatrix,\n"
2634 "#endif\n"
2635 "#ifdef MODE_LIGHTSOURCE\n"
2636 "uniform float4x4 ModelToLight,\n"
2637 "#endif\n"
2638 "#ifdef MODE_LIGHTSOURCE\n"
2639 "uniform float3 LightPosition,\n"
2640 "#endif\n"
2641 "#ifdef MODE_LIGHTDIRECTION\n"
2642 "uniform float3 LightDir,\n"
2643 "#endif\n"
2644 "uniform float4 FogPlane,\n"
2645 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2646 "uniform float3 LightPosition,\n"
2647 "#endif\n"
2648 "\n"
2649 "out float4 gl_FrontColor : COLOR,\n"
2650 "out float4 TexCoordBoth : TEXCOORD0,\n"
2651 "#ifdef USELIGHTMAP\n"
2652 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2653 "#endif\n"
2654 "#ifdef USEEYEVECTOR\n"
2655 "out float3 EyeVector : TEXCOORD2,\n"
2656 "#endif\n"
2657 "#ifdef USEREFLECTION\n"
2658 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2659 "#endif\n"
2660 "#ifdef USEFOG\n"
2661 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2662 "#endif\n"
2663 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2664 "out float3 LightVector : TEXCOORD5,\n"
2665 "#endif\n"
2666 "#ifdef MODE_LIGHTSOURCE\n"
2667 "out float3 CubeVector : TEXCOORD3,\n"
2668 "#endif\n"
2669 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
2670 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2671 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2672 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2673 "#endif\n"
2674 "out float4 gl_Position : POSITION\n"
2675 ")\n"
2676 "{\n"
2677 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2678 "       gl_FrontColor = gl_Color;\n"
2679 "#endif\n"
2680 "       // copy the surface texcoord\n"
2681 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2682 "#ifdef USEVERTEXTEXTUREBLEND\n"
2683 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2684 "#endif\n"
2685 "#ifdef USELIGHTMAP\n"
2686 "       TexCoordLightmap = float2(gl_MultiTexCoord4);\n"
2687 "#endif\n"
2688 "\n"
2689 "#ifdef MODE_LIGHTSOURCE\n"
2690 "       // transform vertex position into light attenuation/cubemap space\n"
2691 "       // (-1 to +1 across the light box)\n"
2692 "       CubeVector = float3(mul(ModelToLight, gl_Vertex));\n"
2693 "\n"
2694 "# ifdef USEDIFFUSE\n"
2695 "       // transform unnormalized light direction into tangent space\n"
2696 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2697 "       //  normalize it per pixel)\n"
2698 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2699 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2700 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2701 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2702 "# endif\n"
2703 "#endif\n"
2704 "\n"
2705 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2706 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2707 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2708 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2709 "#endif\n"
2710 "\n"
2711 "       // transform unnormalized eye direction into tangent space\n"
2712 "#ifdef USEEYEVECTOR\n"
2713 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2714 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2715 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2716 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2717 "#endif\n"
2718 "\n"
2719 "#ifdef USEFOG\n"
2720 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2721 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2722 "#endif\n"
2723 "\n"
2724 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2725 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2726 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2727 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2728 "#endif\n"
2729 "\n"
2730 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2731 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2732 "\n"
2733 "#ifdef USEREFLECTION\n"
2734 "       ModelViewProjectionPosition = gl_Position;\n"
2735 "#endif\n"
2736 "}\n"
2737 "#endif // VERTEX_SHADER\n"
2738 "\n"
2739 "\n"
2740 "\n"
2741 "\n"
2742 "#ifdef FRAGMENT_SHADER\n"
2743 "void main\n"
2744 "(\n"
2745 "#ifdef USEDEFERREDLIGHTMAP\n"
2746 "float2 Pixel : WPOS,\n"
2747 "#endif\n"
2748 "float4 gl_FrontColor : COLOR,\n"
2749 "float4 TexCoordBoth : TEXCOORD0,\n"
2750 "#ifdef USELIGHTMAP\n"
2751 "float2 TexCoordLightmap : TEXCOORD1,\n"
2752 "#endif\n"
2753 "#ifdef USEEYEVECTOR\n"
2754 "float3 EyeVector : TEXCOORD2,\n"
2755 "#endif\n"
2756 "#ifdef USEREFLECTION\n"
2757 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2758 "#endif\n"
2759 "#ifdef USEFOG\n"
2760 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2761 "#endif\n"
2762 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2763 "float3 LightVector : TEXCOORD5,\n"
2764 "#endif\n"
2765 "#ifdef MODE_LIGHTSOURCE\n"
2766 "float3 CubeVector : TEXCOORD3,\n"
2767 "#endif\n"
2768 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2769 "float4 ModelViewPosition : TEXCOORD0,\n"
2770 "#endif\n"
2771 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
2772 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2773 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2774 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2775 "#endif\n"
2776 "\n"
2777 "uniform sampler2D Texture_Normal,\n"
2778 "uniform sampler2D Texture_Color,\n"
2779 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2780 "uniform sampler2D Texture_Gloss,\n"
2781 "#endif\n"
2782 "#ifdef USEGLOW\n"
2783 "uniform sampler2D Texture_Glow,\n"
2784 "#endif\n"
2785 "#ifdef USEVERTEXTEXTUREBLEND\n"
2786 "uniform sampler2D Texture_SecondaryNormal,\n"
2787 "uniform sampler2D Texture_SecondaryColor,\n"
2788 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2789 "uniform sampler2D Texture_SecondaryGloss,\n"
2790 "#endif\n"
2791 "#ifdef USEGLOW\n"
2792 "uniform sampler2D Texture_SecondaryGlow,\n"
2793 "#endif\n"
2794 "#endif\n"
2795 "#ifdef USECOLORMAPPING\n"
2796 "uniform sampler2D Texture_Pants,\n"
2797 "uniform sampler2D Texture_Shirt,\n"
2798 "#endif\n"
2799 "#ifdef USEFOG\n"
2800 "uniform sampler2D Texture_FogMask,\n"
2801 "#endif\n"
2802 "#ifdef USELIGHTMAP\n"
2803 "uniform sampler2D Texture_Lightmap,\n"
2804 "#endif\n"
2805 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2806 "uniform sampler2D Texture_Deluxemap,\n"
2807 "#endif\n"
2808 "#ifdef USEREFLECTION\n"
2809 "uniform sampler2D Texture_Reflection,\n"
2810 "#endif\n"
2811 "\n"
2812 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2813 "uniform sampler2D Texture_ScreenDepth,\n"
2814 "uniform sampler2D Texture_ScreenNormalMap,\n"
2815 "#endif\n"
2816 "#ifdef USEDEFERREDLIGHTMAP\n"
2817 "uniform sampler2D Texture_ScreenDiffuse,\n"
2818 "uniform sampler2D Texture_ScreenSpecular,\n"
2819 "#endif\n"
2820 "\n"
2821 "#ifdef USECOLORMAPPING\n"
2822 "uniform half3 Color_Pants,\n"
2823 "uniform half3 Color_Shirt,\n"
2824 "#endif\n"
2825 "#ifdef USEFOG\n"
2826 "uniform float3 FogColor,\n"
2827 "uniform float FogRangeRecip,\n"
2828 "uniform float FogPlaneViewDist,\n"
2829 "uniform float FogHeightFade,\n"
2830 "#endif\n"
2831 "\n"
2832 "#ifdef USEOFFSETMAPPING\n"
2833 "uniform float OffsetMapping_Scale,\n"
2834 "#endif\n"
2835 "\n"
2836 "#ifdef USEDEFERREDLIGHTMAP\n"
2837 "uniform half2 PixelToScreenTexCoord,\n"
2838 "uniform half3 DeferredMod_Diffuse,\n"
2839 "uniform half3 DeferredMod_Specular,\n"
2840 "#endif\n"
2841 "uniform half3 Color_Ambient,\n"
2842 "uniform half3 Color_Diffuse,\n"
2843 "uniform half3 Color_Specular,\n"
2844 "uniform half SpecularPower,\n"
2845 "#ifdef USEGLOW\n"
2846 "uniform half3 Color_Glow,\n"
2847 "#endif\n"
2848 "uniform half Alpha,\n"
2849 "#ifdef USEREFLECTION\n"
2850 "uniform float4 DistortScaleRefractReflect,\n"
2851 "uniform float4 ScreenScaleRefractReflect,\n"
2852 "uniform float4 ScreenCenterRefractReflect,\n"
2853 "uniform half4 ReflectColor,\n"
2854 "#endif\n"
2855 "#ifdef MODE_LIGHTDIRECTION\n"
2856 "uniform half3 LightColor,\n"
2857 "#endif\n"
2858 "#ifdef MODE_LIGHTSOURCE\n"
2859 "uniform half3 LightColor,\n"
2860 "#endif\n"
2861 "\n"
2862 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2863 "uniform sampler2D Texture_Attenuation,\n"
2864 "uniform samplerCUBE Texture_Cube,\n"
2865 "\n"
2866 "#ifdef USESHADOWMAPRECT\n"
2867 "# ifdef USESHADOWSAMPLER\n"
2868 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2869 "# else\n"
2870 "uniform samplerRECT Texture_ShadowMapRect,\n"
2871 "# endif\n"
2872 "#endif\n"
2873 "\n"
2874 "#ifdef USESHADOWMAP2D\n"
2875 "# ifdef USESHADOWSAMPLER\n"
2876 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2877 "# else\n"
2878 "uniform sampler2D Texture_ShadowMap2D,\n"
2879 "# endif\n"
2880 "#endif\n"
2881 "\n"
2882 "#ifdef USESHADOWMAPVSDCT\n"
2883 "uniform samplerCUBE Texture_CubeProjection,\n"
2884 "#endif\n"
2885 "\n"
2886 "#ifdef USESHADOWMAPCUBE\n"
2887 "# ifdef USESHADOWSAMPLER\n"
2888 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2889 "# else\n"
2890 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2891 "# endif\n"
2892 "#endif\n"
2893 "\n"
2894 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2895 "uniform float2 ShadowMap_TextureScale,\n"
2896 "uniform float4 ShadowMap_Parameters,\n"
2897 "#endif\n"
2898 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2899 "\n"
2900 "out float4 gl_FragColor : COLOR\n"
2901 ")\n"
2902 "{\n"
2903 "       float2 TexCoord = TexCoordBoth.xy;\n"
2904 "#ifdef USEVERTEXTEXTUREBLEND\n"
2905 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
2906 "#endif\n"
2907 "#ifdef USEOFFSETMAPPING\n"
2908 "       // apply offsetmapping\n"
2909 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2910 "#define TexCoord TexCoordOffset\n"
2911 "#endif\n"
2912 "\n"
2913 "       // combine the diffuse textures (base, pants, shirt)\n"
2914 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
2915 "#ifdef USEALPHAKILL\n"
2916 "       if (color.a < 0.5)\n"
2917 "               discard;\n"
2918 "#endif\n"
2919 "       color.a *= Alpha;\n"
2920 "#ifdef USECOLORMAPPING\n"
2921 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord)) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
2922 "#endif\n"
2923 "#ifdef USEVERTEXTEXTUREBLEND\n"
2924 "       float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
2925 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
2926 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
2927 "       color.rgb = half3(lerp(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
2928 "       color.a = 1.0;\n"
2929 "       //color = lerp(half4(1, 0, 0, 1), color, terrainblend);\n"
2930 "#endif\n"
2931 "\n"
2932 "       // get the surface normal\n"
2933 "#ifdef USEVERTEXTEXTUREBLEND\n"
2934 "       half3 surfacenormal = normalize(half3(lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
2935 "#else\n"
2936 "       half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
2937 "#endif\n"
2938 "\n"
2939 "       // get the material colors\n"
2940 "       half3 diffusetex = color.rgb;\n"
2941 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2942 "# ifdef USEVERTEXTEXTUREBLEND\n"
2943 "       half3 glosstex = half3(lerp(float3(tex2D(Texture_SecondaryGloss, TexCoord2)), float3(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
2944 "# else\n"
2945 "       half3 glosstex = half3(tex2D(Texture_Gloss, TexCoord));\n"
2946 "# endif\n"
2947 "#endif\n"
2948 "\n"
2949 "\n"
2950 "\n"
2951 "\n"
2952 "#ifdef MODE_LIGHTSOURCE\n"
2953 "       // light source\n"
2954 "#ifdef USEDIFFUSE\n"
2955 "       half3 lightnormal = half3(normalize(LightVector));\n"
2956 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2957 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
2958 "#ifdef USESPECULAR\n"
2959 "#ifdef USEEXACTSPECULARMATH\n"
2960 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
2961 "#else\n"
2962 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
2963 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
2964 "#endif\n"
2965 "       color.rgb += glosstex * (specular * Color_Specular);\n"
2966 "#endif\n"
2967 "#else\n"
2968 "       color.rgb = diffusetex * Color_Ambient;\n"
2969 "#endif\n"
2970 "       color.rgb *= LightColor;\n"
2971 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2972 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
2973 "       color.rgb *= ShadowMapCompare(CubeVector,\n"
2974 "# if defined(USESHADOWMAP2D)\n"
2975 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2976 "# endif\n"
2977 "# if defined(USESHADOWMAPRECT)\n"
2978 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2979 "# endif\n"
2980 "# if defined(USESHADOWMAPCUBE)\n"
2981 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2982 "# endif\n"
2983 "\n"
2984 "#ifdef USESHADOWMAPVSDCT\n"
2985 ", Texture_CubeProjection\n"
2986 "#endif\n"
2987 "       );\n"
2988 "\n"
2989 "#endif\n"
2990 "# ifdef USECUBEFILTER\n"
2991 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector));\n"
2992 "# endif\n"
2993 "#endif // MODE_LIGHTSOURCE\n"
2994 "\n"
2995 "\n"
2996 "\n"
2997 "\n"
2998 "#ifdef MODE_LIGHTDIRECTION\n"
2999 "#define SHADING\n"
3000 "#ifdef USEDIFFUSE\n"
3001 "       half3 lightnormal = half3(normalize(LightVector));\n"
3002 "#endif\n"
3003 "#define lightcolor LightColor\n"
3004 "#endif // MODE_LIGHTDIRECTION\n"
3005 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3006 "#define SHADING\n"
3007 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3008 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3009 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3010 "       // convert modelspace light vector to tangentspace\n"
3011 "       half3 lightnormal;\n"
3012 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3013 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3014 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3015 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3016 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3017 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3018 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3019 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3020 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3021 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3022 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3023 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3024 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3025 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3026 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3027 "#define SHADING\n"
3028 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3029 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3030 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3031 "#endif\n"
3032 "\n"
3033 "\n"
3034 "\n"
3035 "\n"
3036 "#ifdef MODE_LIGHTMAP\n"
3037 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
3038 "#endif // MODE_LIGHTMAP\n"
3039 "#ifdef MODE_VERTEXCOLOR\n"
3040 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3041 "#endif // MODE_VERTEXCOLOR\n"
3042 "#ifdef MODE_FLATCOLOR\n"
3043 "       color.rgb = diffusetex * Color_Ambient;\n"
3044 "#endif // MODE_FLATCOLOR\n"
3045 "\n"
3046 "\n"
3047 "\n"
3048 "\n"
3049 "#ifdef SHADING\n"
3050 "# ifdef USEDIFFUSE\n"
3051 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3052 "#  ifdef USESPECULAR\n"
3053 "#   ifdef USEEXACTSPECULARMATH\n"
3054 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
3055 "#   else\n"
3056 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3057 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
3058 "#   endif\n"
3059 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
3060 "#  else\n"
3061 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3062 "#  endif\n"
3063 "# else\n"
3064 "       color.rgb = diffusetex * Color_Ambient;\n"
3065 "# endif\n"
3066 "#endif\n"
3067 "\n"
3068 "#ifdef USEDEFERREDLIGHTMAP\n"
3069 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3070 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
3071 "       color.rgb += glosstex * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
3072 "#endif\n"
3073 "\n"
3074 "#ifdef USEGLOW\n"
3075 "#ifdef USEVERTEXTEXTUREBLEND\n"
3076 "       color.rgb += lerp(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
3077 "#else\n"
3078 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
3079 "#endif\n"
3080 "#endif\n"
3081 "\n"
3082 "#ifdef USEFOG\n"
3083 "#ifdef MODE_LIGHTSOURCE\n"
3084 "       color.rgb *= half(FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3085 "#else\n"
3086 "       color.rgb = lerp(FogColor, float3(color.rgb), FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3087 "#endif\n"
3088 "#endif\n"
3089 "\n"
3090 "       // 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"
3091 "#ifdef USEREFLECTION\n"
3092 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3093 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3094 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3095 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
3096 "       // FIXME temporary hack to detect the case that the reflection\n"
3097 "       // gets blackened at edges due to leaving the area that contains actual\n"
3098 "       // content.\n"
3099 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3100 "       // 'appening.\n"
3101 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3102 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3103 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3104 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3105 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3106 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
3107 "#endif\n"
3108 "\n"
3109 "       gl_FragColor = float4(color);\n"
3110 "}\n"
3111 "#endif // FRAGMENT_SHADER\n"
3112 "\n"
3113 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3114 "#endif // !MODE_DEFERREDGEOMETRY\n"
3115 "#endif // !MODE_WATER\n"
3116 "#endif // !MODE_REFRACTION\n"
3117 "#endif // !MODE_BLOOMBLUR\n"
3118 "#endif // !MODE_GENERIC\n"
3119 "#endif // !MODE_POSTPROCESS\n"
3120 "#endif // !MODE_SHOWDEPTH\n"
3121 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3122 ;
3123
3124 char *glslshaderstring = NULL;
3125 char *cgshaderstring = NULL;
3126
3127 //=======================================================================================================================================================
3128
3129 typedef struct shaderpermutationinfo_s
3130 {
3131         const char *pretext;
3132         const char *name;
3133 }
3134 shaderpermutationinfo_t;
3135
3136 typedef struct shadermodeinfo_s
3137 {
3138         const char *vertexfilename;
3139         const char *geometryfilename;
3140         const char *fragmentfilename;
3141         const char *pretext;
3142         const char *name;
3143 }
3144 shadermodeinfo_t;
3145
3146 typedef enum shaderpermutation_e
3147 {
3148         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3149         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3150         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3151         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3152         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3153         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3154         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3155         SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
3156         SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
3157         SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
3158         SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
3159         SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
3160         SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
3161         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3162         SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3163         SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3164         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3165         SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
3166         SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
3167         SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
3168         SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
3169         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3170         SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
3171         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3172         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3173         SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3174         SHADERPERMUTATION_LIMIT = 1<<26, ///< size of permutations array
3175         SHADERPERMUTATION_COUNT = 26 ///< size of shaderpermutationinfo array
3176 }
3177 shaderpermutation_t;
3178
3179 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3180 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3181 {
3182         {"#define USEDIFFUSE\n", " diffuse"},
3183         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3184         {"#define USEVIEWTINT\n", " viewtint"},
3185         {"#define USECOLORMAPPING\n", " colormapping"},
3186         {"#define USESATURATION\n", " saturation"},
3187         {"#define USEFOGINSIDE\n", " foginside"},
3188         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3189         {"#define USEGAMMARAMPS\n", " gammaramps"},
3190         {"#define USECUBEFILTER\n", " cubefilter"},
3191         {"#define USEGLOW\n", " glow"},
3192         {"#define USEBLOOM\n", " bloom"},
3193         {"#define USESPECULAR\n", " specular"},
3194         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3195         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3196         {"#define USEREFLECTION\n", " reflection"},
3197         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3198         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3199         {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3200         {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3201         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3202         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3203         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3204         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3205         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3206         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3207         {"#define USEALPHAKILL\n", " alphakill"},
3208 };
3209
3210 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3211 typedef enum shadermode_e
3212 {
3213         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3214         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3215         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3216         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3217         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3218         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3219         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3220         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3221         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3222         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3223         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3224         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3225         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3226         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3227         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3228         SHADERMODE_COUNT
3229 }
3230 shadermode_t;
3231
3232 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3233 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3234 {
3235         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3236         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3237         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3238         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3239         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3240         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3241         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3242         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3243         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3244         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3245         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3246         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3247         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3248         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3249         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3250 };
3251
3252 #ifdef SUPPORTCG
3253 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3254 {
3255         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3256         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3257         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3258         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3259         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3260         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3261         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3262         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3263         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3264         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3265         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3266         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3267         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3268         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3269         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3270 };
3271 #endif
3272
3273 struct r_glsl_permutation_s;
3274 typedef struct r_glsl_permutation_s
3275 {
3276         /// hash lookup data
3277         struct r_glsl_permutation_s *hashnext;
3278         unsigned int mode;
3279         unsigned int permutation;
3280
3281         /// indicates if we have tried compiling this permutation already
3282         qboolean compiled;
3283         /// 0 if compilation failed
3284         int program;
3285         /// locations of detected uniforms in program object, or -1 if not found
3286         int loc_Texture_First;
3287         int loc_Texture_Second;
3288         int loc_Texture_GammaRamps;
3289         int loc_Texture_Normal;
3290         int loc_Texture_Color;
3291         int loc_Texture_Gloss;
3292         int loc_Texture_Glow;
3293         int loc_Texture_SecondaryNormal;
3294         int loc_Texture_SecondaryColor;
3295         int loc_Texture_SecondaryGloss;
3296         int loc_Texture_SecondaryGlow;
3297         int loc_Texture_Pants;
3298         int loc_Texture_Shirt;
3299         int loc_Texture_FogMask;
3300         int loc_Texture_Lightmap;
3301         int loc_Texture_Deluxemap;
3302         int loc_Texture_Attenuation;
3303         int loc_Texture_Cube;
3304         int loc_Texture_Refraction;
3305         int loc_Texture_Reflection;
3306         int loc_Texture_ShadowMapRect;
3307         int loc_Texture_ShadowMapCube;
3308         int loc_Texture_ShadowMap2D;
3309         int loc_Texture_CubeProjection;
3310         int loc_Texture_ScreenDepth;
3311         int loc_Texture_ScreenNormalMap;
3312         int loc_Texture_ScreenDiffuse;
3313         int loc_Texture_ScreenSpecular;
3314         int loc_Alpha;
3315         int loc_BloomBlur_Parameters;
3316         int loc_ClientTime;
3317         int loc_Color_Ambient;
3318         int loc_Color_Diffuse;
3319         int loc_Color_Specular;
3320         int loc_Color_Glow;
3321         int loc_Color_Pants;
3322         int loc_Color_Shirt;
3323         int loc_DeferredColor_Ambient;
3324         int loc_DeferredColor_Diffuse;
3325         int loc_DeferredColor_Specular;
3326         int loc_DeferredMod_Diffuse;
3327         int loc_DeferredMod_Specular;
3328         int loc_DistortScaleRefractReflect;
3329         int loc_EyePosition;
3330         int loc_FogColor;
3331         int loc_FogHeightFade;
3332         int loc_FogPlane;
3333         int loc_FogPlaneViewDist;
3334         int loc_FogRangeRecip;
3335         int loc_LightColor;
3336         int loc_LightDir;
3337         int loc_LightPosition;
3338         int loc_OffsetMapping_Scale;
3339         int loc_PixelSize;
3340         int loc_ReflectColor;
3341         int loc_ReflectFactor;
3342         int loc_ReflectOffset;
3343         int loc_RefractColor;
3344         int loc_Saturation;
3345         int loc_ScreenCenterRefractReflect;
3346         int loc_ScreenScaleRefractReflect;
3347         int loc_ScreenToDepth;
3348         int loc_ShadowMap_Parameters;
3349         int loc_ShadowMap_TextureScale;
3350         int loc_SpecularPower;
3351         int loc_UserVec1;
3352         int loc_UserVec2;
3353         int loc_UserVec3;
3354         int loc_UserVec4;
3355         int loc_ViewTintColor;
3356         int loc_ViewToLight;
3357         int loc_ModelToLight;
3358         int loc_TexMatrix;
3359         int loc_BackgroundTexMatrix;
3360         int loc_ModelViewProjectionMatrix;
3361         int loc_ModelViewMatrix;
3362         int loc_PixelToScreenTexCoord;
3363 }
3364 r_glsl_permutation_t;
3365
3366 #define SHADERPERMUTATION_HASHSIZE 256
3367
3368 /// information about each possible shader permutation
3369 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3370 /// currently selected permutation
3371 r_glsl_permutation_t *r_glsl_permutation;
3372 /// storage for permutations linked in the hash table
3373 memexpandablearray_t r_glsl_permutationarray;
3374
3375 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3376 {
3377         //unsigned int hashdepth = 0;
3378         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3379         r_glsl_permutation_t *p;
3380         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3381         {
3382                 if (p->mode == mode && p->permutation == permutation)
3383                 {
3384                         //if (hashdepth > 10)
3385                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3386                         return p;
3387                 }
3388                 //hashdepth++;
3389         }
3390         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3391         p->mode = mode;
3392         p->permutation = permutation;
3393         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3394         r_glsl_permutationhash[mode][hashindex] = p;
3395         //if (hashdepth > 10)
3396         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3397         return p;
3398 }
3399
3400 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3401 {
3402         char *shaderstring;
3403         if (!filename || !filename[0])
3404                 return NULL;
3405         if (!strcmp(filename, "glsl/default.glsl"))
3406         {
3407                 if (!glslshaderstring)
3408                 {
3409                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3410                         if (glslshaderstring)
3411                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3412                         else
3413                                 glslshaderstring = (char *)builtinshaderstring;
3414                 }
3415                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3416                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3417                 return shaderstring;
3418         }
3419         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3420         if (shaderstring)
3421         {
3422                 if (printfromdisknotice)
3423                         Con_DPrintf("from disk %s... ", filename);
3424                 return shaderstring;
3425         }
3426         return shaderstring;
3427 }
3428
3429 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3430 {
3431         int i;
3432         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3433         int vertstrings_count = 0;
3434         int geomstrings_count = 0;
3435         int fragstrings_count = 0;
3436         char *vertexstring, *geometrystring, *fragmentstring;
3437         const char *vertstrings_list[32+3];
3438         const char *geomstrings_list[32+3];
3439         const char *fragstrings_list[32+3];
3440         char permutationname[256];
3441
3442         if (p->compiled)
3443                 return;
3444         p->compiled = true;
3445         p->program = 0;
3446
3447         permutationname[0] = 0;
3448         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3449         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3450         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3451
3452         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3453
3454         // the first pretext is which type of shader to compile as
3455         // (later these will all be bound together as a program object)
3456         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3457         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3458         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3459
3460         // the second pretext is the mode (for example a light source)
3461         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3462         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3463         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3464         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3465
3466         // now add all the permutation pretexts
3467         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3468         {
3469                 if (permutation & (1<<i))
3470                 {
3471                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3472                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3473                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3474                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3475                 }
3476                 else
3477                 {
3478                         // keep line numbers correct
3479                         vertstrings_list[vertstrings_count++] = "\n";
3480                         geomstrings_list[geomstrings_count++] = "\n";
3481                         fragstrings_list[fragstrings_count++] = "\n";
3482                 }
3483         }
3484
3485         // now append the shader text itself
3486         vertstrings_list[vertstrings_count++] = vertexstring;
3487         geomstrings_list[geomstrings_count++] = geometrystring;
3488         fragstrings_list[fragstrings_count++] = fragmentstring;
3489
3490         // if any sources were NULL, clear the respective list
3491         if (!vertexstring)
3492                 vertstrings_count = 0;
3493         if (!geometrystring)
3494                 geomstrings_count = 0;
3495         if (!fragmentstring)
3496                 fragstrings_count = 0;
3497
3498         // compile the shader program
3499         if (vertstrings_count + geomstrings_count + fragstrings_count)
3500                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3501         if (p->program)
3502         {
3503                 CHECKGLERROR
3504                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3505                 // look up all the uniform variable names we care about, so we don't
3506                 // have to look them up every time we set them
3507
3508                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3509                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3510                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3511                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3512                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3513                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3514                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3515                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3516                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3517                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3518                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3519                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3520                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3521                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3522                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3523                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3524                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3525                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3526                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3527                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3528                 p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3529                 p->loc_Texture_ShadowMapCube      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3530                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3531                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3532                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3533                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3534                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3535                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3536                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3537                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3538                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3539                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3540                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3541                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3542                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3543                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3544                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3545                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3546                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3547                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3548                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3549                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3550                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3551                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3552                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3553                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3554                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3555                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3556                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3557                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3558                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3559                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3560                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3561                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3562                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3563                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3564                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3565                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3566                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3567                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3568                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3569                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3570                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3571                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3572                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3573                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3574                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3575                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3576                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3577                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3578                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3579                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3580                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3581                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3582                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3583                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3584                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3585                 // initialize the samplers to refer to the texture units we use
3586                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3587                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3588                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3589                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3590                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3591                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3592                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3593                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3594                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3595                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3596                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3597                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3598                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3599                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3600                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3601                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3602                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3603                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3604                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3605                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3606                 if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , GL20TU_SHADOWMAPRECT);
3607                 if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
3608                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
3609                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3610                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3611                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3612                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3613                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3614                 CHECKGLERROR
3615                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3616         }
3617         else
3618                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3619
3620         // free the strings
3621         if (vertexstring)
3622                 Mem_Free(vertexstring);
3623         if (geometrystring)
3624                 Mem_Free(geometrystring);
3625         if (fragmentstring)
3626                 Mem_Free(fragmentstring);
3627 }
3628
3629 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3630 {
3631         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3632         if (r_glsl_permutation != perm)
3633         {
3634                 r_glsl_permutation = perm;
3635                 if (!r_glsl_permutation->program)
3636                 {
3637                         if (!r_glsl_permutation->compiled)
3638                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3639                         if (!r_glsl_permutation->program)
3640                         {
3641                                 // remove features until we find a valid permutation
3642                                 int i;
3643                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3644                                 {
3645                                         // reduce i more quickly whenever it would not remove any bits
3646                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3647                                         if (!(permutation & j))
3648                                                 continue;
3649                                         permutation -= j;
3650                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3651                                         if (!r_glsl_permutation->compiled)
3652                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3653                                         if (r_glsl_permutation->program)
3654                                                 break;
3655                                 }
3656                                 if (i >= SHADERPERMUTATION_COUNT)
3657                                 {
3658                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3659                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3660                                         qglUseProgramObjectARB(0);CHECKGLERROR
3661                                         return; // no bit left to clear, entire mode is broken
3662                                 }
3663                         }
3664                 }
3665                 CHECKGLERROR
3666                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3667         }
3668         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3669         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3670 }
3671
3672 #ifdef SUPPORTCG
3673 #include <Cg/cgGL.h>
3674 struct r_cg_permutation_s;
3675 typedef struct r_cg_permutation_s
3676 {
3677         /// hash lookup data
3678         struct r_cg_permutation_s *hashnext;
3679         unsigned int mode;
3680         unsigned int permutation;
3681
3682         /// indicates if we have tried compiling this permutation already
3683         qboolean compiled;
3684         /// 0 if compilation failed
3685         CGprogram vprogram;
3686         CGprogram fprogram;
3687         /// locations of detected parameters in programs, or NULL if not found
3688         CGparameter vp_EyePosition;
3689         CGparameter vp_FogPlane;
3690         CGparameter vp_LightDir;
3691         CGparameter vp_LightPosition;
3692         CGparameter vp_ModelToLight;
3693         CGparameter vp_TexMatrix;
3694         CGparameter vp_BackgroundTexMatrix;
3695         CGparameter vp_ModelViewProjectionMatrix;
3696         CGparameter vp_ModelViewMatrix;
3697
3698         CGparameter fp_Texture_First;
3699         CGparameter fp_Texture_Second;
3700         CGparameter fp_Texture_GammaRamps;
3701         CGparameter fp_Texture_Normal;
3702         CGparameter fp_Texture_Color;
3703         CGparameter fp_Texture_Gloss;
3704         CGparameter fp_Texture_Glow;
3705         CGparameter fp_Texture_SecondaryNormal;
3706         CGparameter fp_Texture_SecondaryColor;
3707         CGparameter fp_Texture_SecondaryGloss;
3708         CGparameter fp_Texture_SecondaryGlow;
3709         CGparameter fp_Texture_Pants;
3710         CGparameter fp_Texture_Shirt;
3711         CGparameter fp_Texture_FogMask;
3712         CGparameter fp_Texture_Lightmap;
3713         CGparameter fp_Texture_Deluxemap;
3714         CGparameter fp_Texture_Attenuation;
3715         CGparameter fp_Texture_Cube;
3716         CGparameter fp_Texture_Refraction;
3717         CGparameter fp_Texture_Reflection;
3718         CGparameter fp_Texture_ShadowMapRect;
3719         CGparameter fp_Texture_ShadowMapCube;
3720         CGparameter fp_Texture_ShadowMap2D;
3721         CGparameter fp_Texture_CubeProjection;
3722         CGparameter fp_Texture_ScreenDepth;
3723         CGparameter fp_Texture_ScreenNormalMap;
3724         CGparameter fp_Texture_ScreenDiffuse;
3725         CGparameter fp_Texture_ScreenSpecular;
3726         CGparameter fp_Alpha;
3727         CGparameter fp_BloomBlur_Parameters;
3728         CGparameter fp_ClientTime;
3729         CGparameter fp_Color_Ambient;
3730         CGparameter fp_Color_Diffuse;
3731         CGparameter fp_Color_Specular;
3732         CGparameter fp_Color_Glow;
3733         CGparameter fp_Color_Pants;
3734         CGparameter fp_Color_Shirt;
3735         CGparameter fp_DeferredColor_Ambient;
3736         CGparameter fp_DeferredColor_Diffuse;
3737         CGparameter fp_DeferredColor_Specular;
3738         CGparameter fp_DeferredMod_Diffuse;
3739         CGparameter fp_DeferredMod_Specular;
3740         CGparameter fp_DistortScaleRefractReflect;
3741         CGparameter fp_EyePosition;
3742         CGparameter fp_FogColor;
3743         CGparameter fp_FogHeightFade;
3744         CGparameter fp_FogPlane;
3745         CGparameter fp_FogPlaneViewDist;
3746         CGparameter fp_FogRangeRecip;
3747         CGparameter fp_LightColor;
3748         CGparameter fp_LightDir;
3749         CGparameter fp_LightPosition;
3750         CGparameter fp_OffsetMapping_Scale;
3751         CGparameter fp_PixelSize;
3752         CGparameter fp_ReflectColor;
3753         CGparameter fp_ReflectFactor;
3754         CGparameter fp_ReflectOffset;
3755         CGparameter fp_RefractColor;
3756         CGparameter fp_Saturation;
3757         CGparameter fp_ScreenCenterRefractReflect;
3758         CGparameter fp_ScreenScaleRefractReflect;
3759         CGparameter fp_ScreenToDepth;
3760         CGparameter fp_ShadowMap_Parameters;
3761         CGparameter fp_ShadowMap_TextureScale;
3762         CGparameter fp_SpecularPower;
3763         CGparameter fp_UserVec1;
3764         CGparameter fp_UserVec2;
3765         CGparameter fp_UserVec3;
3766         CGparameter fp_UserVec4;
3767         CGparameter fp_ViewTintColor;
3768         CGparameter fp_ViewToLight;
3769         CGparameter fp_PixelToScreenTexCoord;
3770 }
3771 r_cg_permutation_t;
3772
3773 /// information about each possible shader permutation
3774 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3775 /// currently selected permutation
3776 r_cg_permutation_t *r_cg_permutation;
3777 /// storage for permutations linked in the hash table
3778 memexpandablearray_t r_cg_permutationarray;
3779
3780 #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));}}
3781
3782 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3783 {
3784         //unsigned int hashdepth = 0;
3785         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3786         r_cg_permutation_t *p;
3787         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3788         {
3789                 if (p->mode == mode && p->permutation == permutation)
3790                 {
3791                         //if (hashdepth > 10)
3792                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3793                         return p;
3794                 }
3795                 //hashdepth++;
3796         }
3797         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3798         p->mode = mode;
3799         p->permutation = permutation;
3800         p->hashnext = r_cg_permutationhash[mode][hashindex];
3801         r_cg_permutationhash[mode][hashindex] = p;
3802         //if (hashdepth > 10)
3803         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3804         return p;
3805 }
3806
3807 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3808 {
3809         char *shaderstring;
3810         if (!filename || !filename[0])
3811                 return NULL;
3812         if (!strcmp(filename, "cg/default.cg"))
3813         {
3814                 if (!cgshaderstring)
3815                 {
3816                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3817                         if (cgshaderstring)
3818                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3819                         else
3820                                 cgshaderstring = (char *)builtincgshaderstring;
3821                 }
3822                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
3823                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
3824                 return shaderstring;
3825         }
3826         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3827         if (shaderstring)
3828         {
3829                 if (printfromdisknotice)
3830                         Con_DPrintf("from disk %s... ", filename);
3831                 return shaderstring;
3832         }
3833         return shaderstring;
3834 }
3835
3836 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
3837 {
3838         // TODO: load or create .fp and .vp shader files
3839 }
3840
3841 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
3842 {
3843         int i;
3844         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
3845         int vertstrings_count = 0, vertstring_length = 0;
3846         int geomstrings_count = 0, geomstring_length = 0;
3847         int fragstrings_count = 0, fragstring_length = 0;
3848         char *t;
3849         char *vertexstring, *geometrystring, *fragmentstring;
3850         char *vertstring, *geomstring, *fragstring;
3851         const char *vertstrings_list[32+3];
3852         const char *geomstrings_list[32+3];
3853         const char *fragstrings_list[32+3];
3854         char permutationname[256];
3855         char cachename[256];
3856         CGprofile vertexProfile;
3857         CGprofile fragmentProfile;
3858
3859         if (p->compiled)
3860                 return;
3861         p->compiled = true;
3862         p->vprogram = NULL;
3863         p->fprogram = NULL;
3864
3865         permutationname[0] = 0;
3866         cachename[0] = 0;
3867         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
3868         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
3869         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
3870
3871         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3872         strlcat(cachename, "cg/", sizeof(cachename));
3873
3874         // the first pretext is which type of shader to compile as
3875         // (later these will all be bound together as a program object)
3876         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3877         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3878         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3879
3880         // the second pretext is the mode (for example a light source)
3881         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3882         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3883         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3884         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3885         strlcat(cachename, modeinfo->name, sizeof(cachename));
3886
3887         // now add all the permutation pretexts
3888         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3889         {
3890                 if (permutation & (1<<i))
3891                 {
3892                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3893                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3894                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3895                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3896                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
3897                 }
3898                 else
3899                 {
3900                         // keep line numbers correct
3901                         vertstrings_list[vertstrings_count++] = "\n";
3902                         geomstrings_list[geomstrings_count++] = "\n";
3903                         fragstrings_list[fragstrings_count++] = "\n";
3904                 }
3905         }
3906
3907         // replace spaces in the cachename with _ characters
3908         for (i = 0;cachename[i];i++)
3909                 if (cachename[i] == ' ')
3910                         cachename[i] = '_';
3911
3912         // now append the shader text itself
3913         vertstrings_list[vertstrings_count++] = vertexstring;
3914         geomstrings_list[geomstrings_count++] = geometrystring;
3915         fragstrings_list[fragstrings_count++] = fragmentstring;
3916
3917         // if any sources were NULL, clear the respective list
3918         if (!vertexstring)
3919                 vertstrings_count = 0;
3920         if (!geometrystring)
3921                 geomstrings_count = 0;
3922         if (!fragmentstring)
3923                 fragstrings_count = 0;
3924
3925         vertstring_length = 0;
3926         for (i = 0;i < vertstrings_count;i++)
3927                 vertstring_length += strlen(vertstrings_list[i]);
3928         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
3929         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
3930                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
3931
3932         geomstring_length = 0;
3933         for (i = 0;i < geomstrings_count;i++)
3934                 geomstring_length += strlen(geomstrings_list[i]);
3935         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
3936         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
3937                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
3938
3939         fragstring_length = 0;
3940         for (i = 0;i < fragstrings_count;i++)
3941                 fragstring_length += strlen(fragstrings_list[i]);
3942         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
3943         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
3944                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
3945
3946         CHECKGLERROR
3947         CHECKCGERROR
3948         //vertexProfile = CG_PROFILE_ARBVP1;
3949         //fragmentProfile = CG_PROFILE_ARBFP1;
3950         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
3951         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
3952         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
3953         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
3954         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
3955         CHECKGLERROR
3956
3957         // try to load the cached shader, or generate one
3958         R_CG_CacheShader(p, cachename, vertstring, fragstring);
3959
3960         // if caching failed, do a dynamic compile for now
3961         CHECKCGERROR
3962         if (vertstring[0] && !p->vprogram)
3963                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
3964         CHECKCGERROR
3965         if (fragstring[0] && !p->fprogram)
3966                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
3967         CHECKCGERROR
3968
3969         // look up all the uniform variable names we care about, so we don't
3970         // have to look them up every time we set them
3971         if (p->vprogram)
3972         {
3973                 CHECKCGERROR
3974                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
3975                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
3976                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
3977                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
3978                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
3979                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
3980                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
3981                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
3982                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
3983                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
3984                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
3985                 CHECKCGERROR
3986         }
3987         if (p->fprogram)
3988         {
3989                 CHECKCGERROR
3990                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
3991                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
3992                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
3993                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
3994                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
3995                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
3996                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
3997                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
3998                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
3999                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4000                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4001                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4002                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4003                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4004                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4005                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4006                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4007                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4008                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4009                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4010                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4011                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4012                 p->fp_Texture_ShadowMapRect      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
4013                 p->fp_Texture_ShadowMapCube      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
4014                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4015                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4016                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4017                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4018                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4019                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4020                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4021                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4022                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4023                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4024                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4025                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4026                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4027                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4028                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4029                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4030                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4031                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4032                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4033                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4034                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4035                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4036                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4037                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4038                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4039                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4040                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4041                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4042                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4043                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4044                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4045                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4046                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4047                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4048                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4049                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4050                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4051                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4052                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4053                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4054                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4055                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4056                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4057                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4058                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4059                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4060                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4061                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4062                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4063                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4064                 CHECKCGERROR
4065         }
4066
4067         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4068                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4069         else
4070                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4071
4072         // free the strings
4073         if (vertstring)
4074                 Mem_Free(vertstring);
4075         if (geomstring)
4076                 Mem_Free(geomstring);
4077         if (fragstring)
4078                 Mem_Free(fragstring);
4079         if (vertexstring)
4080                 Mem_Free(vertexstring);
4081         if (geometrystring)
4082                 Mem_Free(geometrystring);
4083         if (fragmentstring)
4084                 Mem_Free(fragmentstring);
4085 }
4086
4087 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4088 {
4089         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4090         CHECKGLERROR
4091         CHECKCGERROR
4092         if (r_cg_permutation != perm)
4093         {
4094                 r_cg_permutation = perm;
4095                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4096                 {
4097                         if (!r_cg_permutation->compiled)
4098                                 R_CG_CompilePermutation(perm, mode, permutation);
4099                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4100                         {
4101                                 // remove features until we find a valid permutation
4102                                 int i;
4103                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4104                                 {
4105                                         // reduce i more quickly whenever it would not remove any bits
4106                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4107                                         if (!(permutation & j))
4108                                                 continue;
4109                                         permutation -= j;
4110                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4111                                         if (!r_cg_permutation->compiled)
4112                                                 R_CG_CompilePermutation(perm, mode, permutation);
4113                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4114                                                 break;
4115                                 }
4116                                 if (i >= SHADERPERMUTATION_COUNT)
4117                                 {
4118                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4119                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4120                                         return; // no bit left to clear, entire mode is broken
4121                                 }
4122                         }
4123                 }
4124                 CHECKGLERROR
4125                 CHECKCGERROR
4126                 if (r_cg_permutation->vprogram)
4127                 {
4128                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4129                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4130                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4131                 }
4132                 else
4133                 {
4134                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4135                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4136                 }
4137                 if (r_cg_permutation->fprogram)
4138                 {
4139                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4140                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4141                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4142                 }
4143                 else
4144                 {
4145                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4146                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4147                 }
4148         }
4149         CHECKCGERROR
4150         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4151         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4152 }
4153
4154 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4155 {
4156         cgGLSetTextureParameter(param, R_GetTexture(tex));
4157         cgGLEnableTextureParameter(param);
4158 }
4159 #endif
4160
4161 void R_GLSL_Restart_f(void)
4162 {
4163         unsigned int i, limit;
4164         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4165                 Mem_Free(glslshaderstring);
4166         glslshaderstring = NULL;
4167         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4168                 Mem_Free(cgshaderstring);
4169         cgshaderstring = NULL;
4170         switch(vid.renderpath)
4171         {
4172         case RENDERPATH_GL20:
4173                 {
4174                         r_glsl_permutation_t *p;
4175                         r_glsl_permutation = NULL;
4176                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4177                         for (i = 0;i < limit;i++)
4178                         {
4179                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4180                                 {
4181                                         GL_Backend_FreeProgram(p->program);
4182                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4183                                 }
4184                         }
4185                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4186                 }
4187                 break;
4188         case RENDERPATH_CGGL:
4189 #ifdef SUPPORTCG
4190                 {
4191                         r_cg_permutation_t *p;
4192                         r_cg_permutation = NULL;
4193                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4194                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4195                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4196                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4197                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4198                         for (i = 0;i < limit;i++)
4199                         {
4200                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4201                                 {
4202                                         if (p->vprogram)
4203                                                 cgDestroyProgram(p->vprogram);
4204                                         if (p->fprogram)
4205                                                 cgDestroyProgram(p->fprogram);
4206                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4207                                 }
4208                         }
4209                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4210                 }
4211                 break;
4212 #endif
4213         case RENDERPATH_GL13:
4214         case RENDERPATH_GL11:
4215                 break;
4216         }
4217 }
4218
4219 void R_GLSL_DumpShader_f(void)
4220 {
4221         int i;
4222         qfile_t *file;
4223
4224         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4225         if (file)
4226         {
4227                 FS_Print(file, "/* The engine may define the following macros:\n");
4228                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4229                 for (i = 0;i < SHADERMODE_COUNT;i++)
4230                         FS_Print(file, glslshadermodeinfo[i].pretext);
4231                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4232                         FS_Print(file, shaderpermutationinfo[i].pretext);
4233                 FS_Print(file, "*/\n");
4234                 FS_Print(file, builtinshaderstring);
4235                 FS_Close(file);
4236                 Con_Printf("glsl/default.glsl written\n");
4237         }
4238         else
4239                 Con_Printf("failed to write to glsl/default.glsl\n");
4240
4241 #ifdef SUPPORTCG
4242         file = FS_OpenRealFile("cg/default.cg", "w", false);
4243         if (file)
4244         {
4245                 FS_Print(file, "/* The engine may define the following macros:\n");
4246                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4247                 for (i = 0;i < SHADERMODE_COUNT;i++)
4248                         FS_Print(file, cgshadermodeinfo[i].pretext);
4249                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4250                         FS_Print(file, shaderpermutationinfo[i].pretext);
4251                 FS_Print(file, "*/\n");
4252                 FS_Print(file, builtincgshaderstring);
4253                 FS_Close(file);
4254                 Con_Printf("cg/default.cg written\n");
4255         }
4256         else
4257                 Con_Printf("failed to write to cg/default.cg\n");
4258 #endif
4259 }
4260
4261 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4262 {
4263         if (!second)
4264                 texturemode = GL_MODULATE;
4265         switch (vid.renderpath)
4266         {
4267         case RENDERPATH_GL20:
4268                 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))));
4269                 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
4270                 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, second);
4271                 break;
4272         case RENDERPATH_CGGL:
4273 #ifdef SUPPORTCG
4274                 CHECKCGERROR
4275                 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))));
4276                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4277                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4278 #endif
4279                 break;
4280         case RENDERPATH_GL13:
4281                 R_Mesh_TexBind(0, first );
4282                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4283                 R_Mesh_TexBind(1, second);
4284                 if (second)
4285                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4286                 break;
4287         case RENDERPATH_GL11:
4288                 R_Mesh_TexBind(0, first );
4289                 break;
4290         }
4291 }
4292
4293 void R_SetupShader_DepthOrShadow(void)
4294 {
4295         switch (vid.renderpath)
4296         {
4297         case RENDERPATH_GL20:
4298                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4299                 break;
4300         case RENDERPATH_CGGL:
4301 #ifdef SUPPORTCG
4302                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4303 #endif
4304                 break;
4305         case RENDERPATH_GL13:
4306                 R_Mesh_TexBind(0, 0);
4307                 R_Mesh_TexBind(1, 0);
4308                 break;
4309         case RENDERPATH_GL11:
4310                 R_Mesh_TexBind(0, 0);
4311                 break;
4312         }
4313 }
4314
4315 void R_SetupShader_ShowDepth(void)
4316 {
4317         switch (vid.renderpath)
4318         {
4319         case RENDERPATH_GL20:
4320                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4321                 break;
4322         case RENDERPATH_CGGL:
4323 #ifdef SUPPORTCG
4324                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4325 #endif
4326                 break;
4327         case RENDERPATH_GL13:
4328                 break;
4329         case RENDERPATH_GL11:
4330                 break;
4331         }
4332 }
4333
4334 extern qboolean r_shadow_usingdeferredprepass;
4335 extern cvar_t r_shadow_deferred_8bitrange;
4336 extern rtexture_t *r_shadow_attenuationgradienttexture;
4337 extern rtexture_t *r_shadow_attenuation2dtexture;
4338 extern rtexture_t *r_shadow_attenuation3dtexture;
4339 extern qboolean r_shadow_usingshadowmaprect;
4340 extern qboolean r_shadow_usingshadowmapcube;
4341 extern qboolean r_shadow_usingshadowmap2d;
4342 extern float r_shadow_shadowmap_texturescale[2];
4343 extern float r_shadow_shadowmap_parameters[4];
4344 extern qboolean r_shadow_shadowmapvsdct;
4345 extern qboolean r_shadow_shadowmapsampler;
4346 extern int r_shadow_shadowmappcf;
4347 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4348 extern rtexture_t *r_shadow_shadowmap2dtexture;
4349 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4350 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4351 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4352 extern int r_shadow_prepass_width;
4353 extern int r_shadow_prepass_height;
4354 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4355 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4356 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4357 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4358 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
4359 {
4360         // select a permutation of the lighting shader appropriate to this
4361         // combination of texture, entity, light source, and fogging, only use the
4362         // minimum features necessary to avoid wasting rendering time in the
4363         // fragment shader on features that are not being used
4364         unsigned int permutation = 0;
4365         unsigned int mode = 0;
4366         float m16f[16];
4367         if (rsurfacepass == RSURFPASS_BACKGROUND)
4368         {
4369                 // distorted background
4370                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4371                         mode = SHADERMODE_WATER;
4372                 else
4373                         mode = SHADERMODE_REFRACTION;
4374                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4375                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4376                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4377                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4378                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4379                 R_Mesh_ColorPointer(NULL, 0, 0);
4380                 GL_AlphaTest(false);
4381                 GL_BlendFunc(GL_ONE, GL_ZERO);
4382         }
4383         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4384         {
4385                 if (r_glsl_offsetmapping.integer)
4386                 {
4387                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4388                         if (r_glsl_offsetmapping_reliefmapping.integer)
4389                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4390                 }
4391                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4392                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4393                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4394                         permutation |= SHADERPERMUTATION_ALPHAKILL;
4395                 // normalmap (deferred prepass), may use alpha test on diffuse
4396                 mode = SHADERMODE_DEFERREDGEOMETRY;
4397                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4398                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4399                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4400                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4401                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4402                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4403                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4404                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4405                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4406                 else
4407                         R_Mesh_ColorPointer(NULL, 0, 0);
4408                 GL_AlphaTest(false);
4409                 GL_BlendFunc(GL_ONE, GL_ZERO);
4410         }
4411         else if (rsurfacepass == RSURFPASS_RTLIGHT)
4412         {
4413                 if (r_glsl_offsetmapping.integer)
4414                 {
4415                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4416                         if (r_glsl_offsetmapping_reliefmapping.integer)
4417                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4418                 }
4419                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4420                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4421                 // light source
4422                 mode = SHADERMODE_LIGHTSOURCE;
4423                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4424                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4425                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4426                         permutation |= SHADERPERMUTATION_CUBEFILTER;
4427                 if (diffusescale > 0)
4428                         permutation |= SHADERPERMUTATION_DIFFUSE;
4429                 if (specularscale > 0)
4430                 {
4431                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4432                         if (r_shadow_glossexact.integer)
4433                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4434                 }
4435                 if (r_refdef.fogenabled)
4436                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4437                 if (rsurface.texture->colormapping)
4438                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4439                 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4440                 {
4441                         if (r_shadow_usingshadowmaprect)
4442                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4443                         if (r_shadow_usingshadowmap2d)
4444                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4445                         if (r_shadow_usingshadowmapcube)
4446                                 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4447                         else if(r_shadow_shadowmapvsdct)
4448                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4449
4450                         if (r_shadow_shadowmapsampler)
4451                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4452                         if (r_shadow_shadowmappcf > 1)
4453                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4454                         else if (r_shadow_shadowmappcf)
4455                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4456                 }
4457                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4458                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4459                 {
4460                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4461                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4462                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4463                 }
4464                 else
4465                 {
4466                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4467                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4468                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4469                 }
4470                 //R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4471                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4472                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4473                 else
4474                         R_Mesh_ColorPointer(NULL, 0, 0);
4475                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4476                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4477         }
4478         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4479         {
4480                 if (r_glsl_offsetmapping.integer)
4481                 {
4482                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4483                         if (r_glsl_offsetmapping_reliefmapping.integer)
4484                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4485                 }
4486                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4487                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4488                 // unshaded geometry (fullbright or ambient model lighting)
4489                 mode = SHADERMODE_FLATCOLOR;
4490                 ambientscale = diffusescale = specularscale = 0;
4491                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4492                         permutation |= SHADERPERMUTATION_GLOW;
4493                 if (r_refdef.fogenabled)
4494                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4495                 if (rsurface.texture->colormapping)
4496                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4497                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4498                         permutation |= SHADERPERMUTATION_REFLECTION;
4499                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4500                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4501                 {
4502                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4503                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4504                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4505                 }
4506                 else
4507                 {
4508                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4509                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4510                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4511                 }
4512                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4513                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4514                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4515                 else
4516                         R_Mesh_ColorPointer(NULL, 0, 0);
4517                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4518                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4519         }
4520         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4521         {
4522                 if (r_glsl_offsetmapping.integer)
4523                 {
4524                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4525                         if (r_glsl_offsetmapping_reliefmapping.integer)
4526                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4527                 }
4528                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4529                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4530                 // directional model lighting
4531                 mode = SHADERMODE_LIGHTDIRECTION;
4532                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4533                         permutation |= SHADERPERMUTATION_GLOW;
4534                 permutation |= SHADERPERMUTATION_DIFFUSE;
4535                 if (specularscale > 0)
4536                 {
4537                         permutation |= SHADERPERMUTATION_SPECULAR;
4538                         if (r_shadow_glossexact.integer)
4539                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4540                 }
4541                 if (r_refdef.fogenabled)
4542                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4543                 if (rsurface.texture->colormapping)
4544                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4545                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4546                         permutation |= SHADERPERMUTATION_REFLECTION;
4547                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4548                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4549                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4550                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4551                 {
4552                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4553                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4554                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4555                 }
4556                 else
4557                 {
4558                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4559                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4560                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4561                 }
4562                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4563                 R_Mesh_ColorPointer(NULL, 0, 0);
4564                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4565                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4566         }
4567         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
4568         {
4569                 if (r_glsl_offsetmapping.integer)
4570                 {
4571                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4572                         if (r_glsl_offsetmapping_reliefmapping.integer)
4573                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4574                 }
4575                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4576                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4577                 // ambient model lighting
4578                 mode = SHADERMODE_LIGHTDIRECTION;
4579                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4580                         permutation |= SHADERPERMUTATION_GLOW;
4581                 if (r_refdef.fogenabled)
4582                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4583                 if (rsurface.texture->colormapping)
4584                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4585                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4586                         permutation |= SHADERPERMUTATION_REFLECTION;
4587                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4588                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4589                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4590                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4591                 {
4592                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4593                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4594                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4595                 }
4596                 else
4597                 {
4598                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4599                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4600                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4601                 }
4602                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4603                 R_Mesh_ColorPointer(NULL, 0, 0);
4604                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4605                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4606         }
4607         else
4608         {
4609                 if (r_glsl_offsetmapping.integer)
4610                 {
4611                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4612                         if (r_glsl_offsetmapping_reliefmapping.integer)
4613                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4614                 }
4615                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4616                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4617                 // lightmapped wall
4618                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4619                         permutation |= SHADERPERMUTATION_GLOW;
4620                 if (r_refdef.fogenabled)
4621                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4622                 if (rsurface.texture->colormapping)
4623                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4624                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4625                         permutation |= SHADERPERMUTATION_REFLECTION;
4626                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4627                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4628                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
4629                 {
4630                         // deluxemapping (light direction texture)
4631                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
4632                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
4633                         else
4634                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4635                         permutation |= SHADERPERMUTATION_DIFFUSE;
4636                         if (specularscale > 0)
4637                         {
4638                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4639                                 if (r_shadow_glossexact.integer)
4640                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4641                         }
4642                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4643                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4644                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4645                         else
4646                                 R_Mesh_ColorPointer(NULL, 0, 0);
4647                 }
4648                 else if (r_glsl_deluxemapping.integer >= 2)
4649                 {
4650                         // fake deluxemapping (uniform light direction in tangentspace)
4651                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4652                         permutation |= SHADERPERMUTATION_DIFFUSE;
4653                         if (specularscale > 0)
4654                         {
4655                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4656                                 if (r_shadow_glossexact.integer)
4657                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4658                         }
4659                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4660                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4661                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4662                         else
4663                                 R_Mesh_ColorPointer(NULL, 0, 0);
4664                 }
4665                 else if (rsurface.uselightmaptexture)
4666                 {
4667                         // ordinary lightmapping (q1bsp, q3bsp)
4668                         mode = SHADERMODE_LIGHTMAP;
4669                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4670                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4671                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4672                         else
4673                                 R_Mesh_ColorPointer(NULL, 0, 0);
4674                 }
4675                 else
4676                 {
4677                         // ordinary vertex coloring (q3bsp)
4678                         mode = SHADERMODE_VERTEXCOLOR;
4679                         R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4680                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4681                 }
4682                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4683                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4684                 {
4685                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4686                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4687                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4688                 }
4689                 else
4690                 {
4691                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4692                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4693                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4694                 }
4695                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4696                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4697         }
4698         switch(vid.renderpath)
4699         {
4700         case RENDERPATH_GL20:
4701                 R_SetupShader_SetPermutationGLSL(mode, permutation);
4702                 if (mode == SHADERMODE_LIGHTSOURCE)
4703                 {
4704                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
4705                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
4706                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
4707                         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);
4708                         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);
4709                         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);
4710         
4711                         // additive passes are only darkened by fog, not tinted
4712                         if (r_glsl_permutation->loc_FogColor >= 0)
4713                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4714                         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]);
4715                         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]);
4716                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4717                 }
4718                 else
4719                 {
4720                         if (mode == SHADERMODE_FLATCOLOR)
4721                         {
4722                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
4723                         }
4724                         else if (mode == SHADERMODE_LIGHTDIRECTION)
4725                         {
4726                                 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]);
4727                                 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]);
4728                                 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);
4729                                 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);
4730                                 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);
4731                                 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]);
4732                                 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]);
4733                         }
4734                         else
4735                         {
4736                                 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]);
4737                                 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]);
4738                                 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);
4739                                 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);
4740                                 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);
4741                         }
4742                         // additive passes are only darkened by fog, not tinted
4743                         if (r_glsl_permutation->loc_FogColor >= 0)
4744                         {
4745                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4746                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4747                                 else
4748                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4749                         }
4750                         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);
4751                         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]);
4752                         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]);
4753                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
4754                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
4755                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
4756                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
4757                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4758                 }
4759                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
4760                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
4761                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
4762                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
4763                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
4764                 if (r_glsl_permutation->loc_Color_Pants >= 0)
4765                 {
4766                         if (rsurface.texture->pantstexture)
4767                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4768                         else
4769                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
4770                 }
4771                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
4772                 {
4773                         if (rsurface.texture->shirttexture)
4774                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4775                         else
4776                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
4777                 }
4778                 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]);
4779                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
4780                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
4781                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
4782                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
4783                 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]);
4784                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
4785
4786         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
4787         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
4788         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
4789                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
4790                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
4791                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
4792                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
4793                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
4794                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
4795                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
4796                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
4797                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
4798                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
4799                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
4800                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_white                                     );
4801                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_blanknormalmap                            );
4802                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
4803                 if (r_glsl_permutation->loc_Texture_Refraction      >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , r_texture_white                                     );
4804                 if (r_glsl_permutation->loc_Texture_Reflection      >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , r_texture_white                                     );
4805                 if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
4806                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
4807                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
4808                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
4809                 if (rsurface.rtlight)
4810                 {
4811                         if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
4812                         if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT     , r_shadow_shadowmaprectangletexture                  );
4813                         if (r_shadow_usingshadowmapcube)
4814                                 if (r_glsl_permutation->loc_Texture_ShadowMapCube   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE     , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
4815                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D       , r_shadow_shadowmap2dtexture                         );
4816                         if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
4817                 }
4818                 CHECKGLERROR
4819                 break;
4820         case RENDERPATH_CGGL:
4821 #ifdef SUPPORTCG
4822                 R_SetupShader_SetPermutationCG(mode, permutation);
4823                 if (mode == SHADERMODE_LIGHTSOURCE)
4824                 {
4825                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
4826                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4827                 }
4828                 else
4829                 {
4830                         if (mode == SHADERMODE_LIGHTDIRECTION)
4831                         {
4832                                 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
4833                         }
4834                 }
4835                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
4836                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
4837                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4838                 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
4839                 CHECKGLERROR
4840
4841                 if (mode == SHADERMODE_LIGHTSOURCE)
4842                 {
4843                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4844                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
4845                         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
4846                         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
4847                         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
4848
4849                         // additive passes are only darkened by fog, not tinted
4850                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
4851                         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
4852                         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
4853                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4854                 }
4855                 else
4856                 {
4857                         if (mode == SHADERMODE_FLATCOLOR)
4858                         {
4859                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);CHECKCGERROR
4860                         }
4861                         else if (mode == SHADERMODE_LIGHTDIRECTION)
4862                         {
4863                                 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
4864                                 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
4865                                 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
4866                                 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
4867                                 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
4868                                 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
4869                                 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
4870                         }
4871                         else
4872                         {
4873                                 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
4874                                 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
4875                                 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
4876                                 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
4877                                 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
4878                         }
4879                         // additive passes are only darkened by fog, not tinted
4880                         if (r_cg_permutation->fp_FogColor)
4881                         {
4882                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4883                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
4884                                 else
4885                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4886                                 CHECKCGERROR
4887                         }
4888                         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
4889                         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
4890                         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
4891                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
4892                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
4893                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
4894                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
4895                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4896                 }
4897                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
4898                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
4899                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4900                 if (r_cg_permutation->fp_Color_Pants)
4901                 {
4902                         if (rsurface.texture->pantstexture)
4903                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4904                         else
4905                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
4906                         CHECKCGERROR
4907                 }
4908                 if (r_cg_permutation->fp_Color_Shirt)
4909                 {
4910                         if (rsurface.texture->shirttexture)
4911                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4912                         else
4913                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
4914                         CHECKCGERROR
4915                 }
4916                 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
4917                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
4918                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
4919                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
4920                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
4921                 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
4922                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
4923
4924         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
4925         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
4926         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
4927                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
4928                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
4929                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
4930                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
4931                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
4932                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
4933                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
4934                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
4935                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
4936                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
4937                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
4938                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , r_texture_white                                     );CHECKCGERROR
4939                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , r_texture_blanknormalmap                            );CHECKCGERROR
4940                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
4941                 if (r_cg_permutation->fp_Texture_Refraction     ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction     , r_texture_white                                     );CHECKCGERROR
4942                 if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , r_texture_white                                     );CHECKCGERROR
4943                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
4944                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
4945                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
4946                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
4947                 if (rsurface.rtlight)
4948                 {
4949                         if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
4950                         if (r_cg_permutation->fp_Texture_ShadowMapRect  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
4951                         if (r_shadow_usingshadowmapcube)
4952                                 if (r_cg_permutation->fp_Texture_ShadowMapCube  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
4953                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
4954                         if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
4955                 }
4956
4957                 CHECKGLERROR
4958 #endif
4959                 break;
4960         case RENDERPATH_GL13:
4961         case RENDERPATH_GL11:
4962                 break;
4963         }
4964 }
4965
4966 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
4967 {
4968         // select a permutation of the lighting shader appropriate to this
4969         // combination of texture, entity, light source, and fogging, only use the
4970         // minimum features necessary to avoid wasting rendering time in the
4971         // fragment shader on features that are not being used
4972         unsigned int permutation = 0;
4973         unsigned int mode = 0;
4974         const float *lightcolorbase = rtlight->currentcolor;
4975         float ambientscale = rtlight->ambientscale;
4976         float diffusescale = rtlight->diffusescale;
4977         float specularscale = rtlight->specularscale;
4978         // this is the location of the light in view space
4979         vec3_t viewlightorigin;
4980         // this transforms from view space (camera) to light space (cubemap)
4981         matrix4x4_t viewtolight;
4982         matrix4x4_t lighttoview;
4983         float viewtolight16f[16];
4984         float range = 1.0f / r_shadow_deferred_8bitrange.value;
4985         // light source
4986         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
4987         if (rtlight->currentcubemap != r_texture_whitecube)
4988                 permutation |= SHADERPERMUTATION_CUBEFILTER;
4989         if (diffusescale > 0)
4990                 permutation |= SHADERPERMUTATION_DIFFUSE;
4991         if (specularscale > 0)
4992         {
4993                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4994                 if (r_shadow_glossexact.integer)
4995                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4996         }
4997         if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4998         {
4999                 if (r_shadow_usingshadowmaprect)
5000                         permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5001                 if (r_shadow_usingshadowmap2d)
5002                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5003                 if (r_shadow_usingshadowmapcube)
5004                         permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
5005                 else if(r_shadow_shadowmapvsdct)
5006                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5007
5008                 if (r_shadow_shadowmapsampler)
5009                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5010                 if (r_shadow_shadowmappcf > 1)
5011                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5012                 else if (r_shadow_shadowmappcf)
5013                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5014         }
5015         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
5016         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
5017         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
5018         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
5019         switch(vid.renderpath)
5020         {
5021         case RENDERPATH_GL20:
5022                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5023                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5024                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
5025                 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);
5026                 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);
5027                 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);
5028                 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]);
5029                 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]);
5030                 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));
5031                 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]);
5032                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5033
5034                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
5035                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
5036                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
5037                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
5038                 if (r_glsl_permutation->loc_Texture_ShadowMapRect     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT      , r_shadow_shadowmaprectangletexture                  );
5039                 if (r_shadow_usingshadowmapcube)
5040                         if (r_glsl_permutation->loc_Texture_ShadowMapCube     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE      , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5041                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
5042                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
5043                 break;
5044         case RENDERPATH_CGGL:
5045 #ifdef SUPPORTCG
5046                 R_SetupShader_SetPermutationCG(mode, permutation);
5047                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
5048                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
5049                 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
5050                 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
5051                 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
5052                 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
5053                 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
5054                 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
5055                 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
5056                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5057
5058                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
5059                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
5060                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
5061                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
5062                 if (r_cg_permutation->fp_Texture_ShadowMapRect    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
5063                 if (r_shadow_usingshadowmapcube)
5064                         if (r_cg_permutation->fp_Texture_ShadowMapCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5065                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5066                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
5067 #endif
5068                 break;
5069         case RENDERPATH_GL13:
5070         case RENDERPATH_GL11:
5071                 break;
5072         }
5073 }
5074
5075 #define SKINFRAME_HASH 1024
5076
5077 typedef struct
5078 {
5079         int loadsequence; // incremented each level change
5080         memexpandablearray_t array;
5081         skinframe_t *hash[SKINFRAME_HASH];
5082 }
5083 r_skinframe_t;
5084 r_skinframe_t r_skinframe;
5085
5086 void R_SkinFrame_PrepareForPurge(void)
5087 {
5088         r_skinframe.loadsequence++;
5089         // wrap it without hitting zero
5090         if (r_skinframe.loadsequence >= 200)
5091                 r_skinframe.loadsequence = 1;
5092 }
5093
5094 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5095 {
5096         if (!skinframe)
5097                 return;
5098         // mark the skinframe as used for the purging code
5099         skinframe->loadsequence = r_skinframe.loadsequence;
5100 }
5101
5102 void R_SkinFrame_Purge(void)
5103 {
5104         int i;
5105         skinframe_t *s;
5106         for (i = 0;i < SKINFRAME_HASH;i++)
5107         {
5108                 for (s = r_skinframe.hash[i];s;s = s->next)
5109                 {
5110                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5111                         {
5112                                 if (s->merged == s->base)
5113                                         s->merged = NULL;
5114                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5115                                 R_PurgeTexture(s->stain );s->stain  = NULL;
5116                                 R_PurgeTexture(s->merged);s->merged = NULL;
5117                                 R_PurgeTexture(s->base  );s->base   = NULL;
5118                                 R_PurgeTexture(s->pants );s->pants  = NULL;
5119                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
5120                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
5121                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
5122                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
5123                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
5124                                 s->loadsequence = 0;
5125                         }
5126                 }
5127         }
5128 }
5129
5130 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5131         skinframe_t *item;
5132         char basename[MAX_QPATH];
5133
5134         Image_StripImageExtension(name, basename, sizeof(basename));
5135
5136         if( last == NULL ) {
5137                 int hashindex;
5138                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5139                 item = r_skinframe.hash[hashindex];
5140         } else {
5141                 item = last->next;
5142         }
5143
5144         // linearly search through the hash bucket
5145         for( ; item ; item = item->next ) {
5146                 if( !strcmp( item->basename, basename ) ) {
5147                         return item;
5148                 }
5149         }
5150         return NULL;
5151 }
5152
5153 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5154 {
5155         skinframe_t *item;
5156         int hashindex;
5157         char basename[MAX_QPATH];
5158
5159         Image_StripImageExtension(name, basename, sizeof(basename));
5160
5161         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5162         for (item = r_skinframe.hash[hashindex];item;item = item->next)
5163                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5164                         break;
5165
5166         if (!item) {
5167                 rtexture_t *dyntexture;
5168                 // check whether its a dynamic texture
5169                 dyntexture = CL_GetDynTexture( basename );
5170                 if (!add && !dyntexture)
5171                         return NULL;
5172                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5173                 memset(item, 0, sizeof(*item));
5174                 strlcpy(item->basename, basename, sizeof(item->basename));
5175                 item->base = dyntexture; // either NULL or dyntexture handle
5176                 item->textureflags = textureflags;
5177                 item->comparewidth = comparewidth;
5178                 item->compareheight = compareheight;
5179                 item->comparecrc = comparecrc;
5180                 item->next = r_skinframe.hash[hashindex];
5181                 r_skinframe.hash[hashindex] = item;
5182         }
5183         else if( item->base == NULL )
5184         {
5185                 rtexture_t *dyntexture;
5186                 // check whether its a dynamic texture
5187                 // 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]
5188                 dyntexture = CL_GetDynTexture( basename );
5189                 item->base = dyntexture; // either NULL or dyntexture handle
5190         }
5191
5192         R_SkinFrame_MarkUsed(item);
5193         return item;
5194 }
5195
5196 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5197         { \
5198                 unsigned long long avgcolor[5], wsum; \
5199                 int pix, comp, w; \
5200                 avgcolor[0] = 0; \
5201                 avgcolor[1] = 0; \
5202                 avgcolor[2] = 0; \
5203                 avgcolor[3] = 0; \
5204                 avgcolor[4] = 0; \
5205                 wsum = 0; \
5206                 for(pix = 0; pix < cnt; ++pix) \
5207                 { \
5208                         w = 0; \
5209                         for(comp = 0; comp < 3; ++comp) \
5210                                 w += getpixel; \
5211                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5212                         { \
5213                                 ++wsum; \
5214                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5215                                 w = getpixel; \
5216                                 for(comp = 0; comp < 3; ++comp) \
5217                                         avgcolor[comp] += getpixel * w; \
5218                                 avgcolor[3] += w; \
5219                         } \
5220                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5221                         avgcolor[4] += getpixel; \
5222                 } \
5223                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5224                         avgcolor[3] = 1; \
5225                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5226                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5227                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5228                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5229         }
5230
5231 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5232 {
5233         int j;
5234         unsigned char *pixels;
5235         unsigned char *bumppixels;
5236         unsigned char *basepixels = NULL;
5237         int basepixels_width = 0;
5238         int basepixels_height = 0;
5239         skinframe_t *skinframe;
5240         rtexture_t *ddsbase = NULL;
5241         qboolean ddshasalpha = false;
5242         float ddsavgcolor[4];
5243         char basename[MAX_QPATH];
5244
5245         if (cls.state == ca_dedicated)
5246                 return NULL;
5247
5248         // return an existing skinframe if already loaded
5249         // if loading of the first image fails, don't make a new skinframe as it
5250         // would cause all future lookups of this to be missing
5251         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5252         if (skinframe && skinframe->base)
5253                 return skinframe;
5254
5255         Image_StripImageExtension(name, basename, sizeof(basename));
5256
5257         // check for DDS texture file first
5258         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor)))
5259         {
5260                 basepixels = loadimagepixelsbgra(name, complain, true);
5261                 if (basepixels == NULL)
5262                         return NULL;
5263         }
5264
5265         if (developer_loading.integer)
5266                 Con_Printf("loading skin \"%s\"\n", name);
5267
5268         // we've got some pixels to store, so really allocate this new texture now
5269         if (!skinframe)
5270                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5271         skinframe->stain = NULL;
5272         skinframe->merged = NULL;
5273         skinframe->base = NULL;
5274         skinframe->pants = NULL;
5275         skinframe->shirt = NULL;
5276         skinframe->nmap = NULL;
5277         skinframe->gloss = NULL;
5278         skinframe->glow = NULL;
5279         skinframe->fog = NULL;
5280         skinframe->hasalpha = false;
5281
5282         if (ddsbase)
5283         {
5284                 skinframe->base = ddsbase;
5285                 skinframe->hasalpha = ddshasalpha;
5286                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5287                 if (r_loadfog && skinframe->hasalpha)
5288                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5289                 //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]);
5290         }
5291         else
5292         {
5293                 basepixels_width = image_width;
5294                 basepixels_height = image_height;
5295                 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);
5296                 if (textureflags & TEXF_ALPHA)
5297                 {
5298                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5299                         {
5300                                 if (basepixels[j] < 255)
5301                                 {
5302                                         skinframe->hasalpha = true;
5303                                         break;
5304                                 }
5305                         }
5306                         if (r_loadfog && skinframe->hasalpha)
5307                         {
5308                                 // has transparent pixels
5309                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5310                                 for (j = 0;j < image_width * image_height * 4;j += 4)
5311                                 {
5312                                         pixels[j+0] = 255;
5313                                         pixels[j+1] = 255;
5314                                         pixels[j+2] = 255;
5315                                         pixels[j+3] = basepixels[j+3];
5316                                 }
5317                                 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);
5318                                 Mem_Free(pixels);
5319                         }
5320                 }
5321                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5322                 //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]);
5323                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5324                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true);
5325                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
5326                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true);
5327         }
5328
5329         if (r_loaddds)
5330         {
5331                 if (r_loadnormalmap)
5332                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5333                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL);
5334                 if (r_loadgloss)
5335                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL);
5336                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL);
5337                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL);
5338         }
5339
5340         // _norm is the name used by tenebrae and has been adopted as standard
5341         if (r_loadnormalmap && skinframe->nmap == NULL)
5342         {
5343                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
5344                 {
5345                         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);
5346                         Mem_Free(pixels);
5347                         pixels = NULL;
5348                 }
5349                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
5350                 {
5351                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5352                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5353                         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);
5354                         Mem_Free(pixels);
5355                         Mem_Free(bumppixels);
5356                 }
5357                 else if (r_shadow_bumpscale_basetexture.value > 0)
5358                 {
5359                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5360                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5361                         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);
5362                         Mem_Free(pixels);
5363                 }
5364                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
5365                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true);
5366         }
5367
5368         // _luma is supported only for tenebrae compatibility
5369         // _glow is the preferred name
5370         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false))))
5371         {
5372                 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);
5373                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
5374                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true);
5375                 Mem_Free(pixels);pixels = NULL;
5376         }
5377
5378         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false)))
5379         {
5380                 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);
5381                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
5382                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true);
5383                 Mem_Free(pixels);
5384                 pixels = NULL;
5385         }
5386
5387         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false)))
5388         {
5389                 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);
5390                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
5391                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true);
5392                 Mem_Free(pixels);
5393                 pixels = NULL;
5394         }
5395
5396         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false)))
5397         {
5398                 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);
5399                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
5400                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true);
5401                 Mem_Free(pixels);
5402                 pixels = NULL;
5403         }
5404
5405         if (basepixels)
5406                 Mem_Free(basepixels);
5407
5408         return skinframe;
5409 }
5410
5411 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
5412 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
5413 {
5414         int i;
5415         unsigned char *temp1, *temp2;
5416         skinframe_t *skinframe;
5417
5418         if (cls.state == ca_dedicated)
5419                 return NULL;
5420
5421         // if already loaded just return it, otherwise make a new skinframe
5422         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
5423         if (skinframe && skinframe->base)
5424                 return skinframe;
5425
5426         skinframe->stain = NULL;
5427         skinframe->merged = NULL;
5428         skinframe->base = NULL;
5429         skinframe->pants = NULL;
5430         skinframe->shirt = NULL;
5431         skinframe->nmap = NULL;
5432         skinframe->gloss = NULL;
5433         skinframe->glow = NULL;
5434         skinframe->fog = NULL;
5435         skinframe->hasalpha = false;
5436
5437         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5438         if (!skindata)
5439                 return NULL;
5440
5441         if (developer_loading.integer)
5442                 Con_Printf("loading 32bit skin \"%s\"\n", name);
5443
5444         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
5445         {
5446                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5447                 temp2 = temp1 + width * height * 4;
5448                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5449                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5450                 Mem_Free(temp1);
5451         }
5452         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5453         if (textureflags & TEXF_ALPHA)
5454         {
5455                 for (i = 3;i < width * height * 4;i += 4)
5456                 {
5457                         if (skindata[i] < 255)
5458                         {
5459                                 skinframe->hasalpha = true;
5460                                 break;
5461                         }
5462                 }
5463                 if (r_loadfog && skinframe->hasalpha)
5464                 {
5465                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
5466                         memcpy(fogpixels, skindata, width * height * 4);
5467                         for (i = 0;i < width * height * 4;i += 4)
5468                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
5469                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5470                         Mem_Free(fogpixels);
5471                 }
5472         }
5473
5474         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
5475         //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]);
5476
5477         return skinframe;
5478 }
5479
5480 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
5481 {
5482         int i;
5483         int featuresmask;
5484         skinframe_t *skinframe;
5485
5486         if (cls.state == ca_dedicated)
5487                 return NULL;
5488
5489         // if already loaded just return it, otherwise make a new skinframe
5490         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5491         if (skinframe && skinframe->base)
5492                 return skinframe;
5493
5494         skinframe->stain = NULL;
5495         skinframe->merged = NULL;
5496         skinframe->base = NULL;
5497         skinframe->pants = NULL;
5498         skinframe->shirt = NULL;
5499         skinframe->nmap = NULL;
5500         skinframe->gloss = NULL;
5501         skinframe->glow = NULL;
5502         skinframe->fog = NULL;
5503         skinframe->hasalpha = false;
5504
5505         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5506         if (!skindata)
5507                 return NULL;
5508
5509         if (developer_loading.integer)
5510                 Con_Printf("loading quake skin \"%s\"\n", name);
5511
5512         // 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)
5513         skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
5514         memcpy(skinframe->qpixels, skindata, width*height);
5515         skinframe->qwidth = width;
5516         skinframe->qheight = height;
5517
5518         featuresmask = 0;
5519         for (i = 0;i < width * height;i++)
5520                 featuresmask |= palette_featureflags[skindata[i]];
5521
5522         skinframe->hasalpha = false;
5523         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
5524         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
5525         skinframe->qgeneratemerged = true;
5526         skinframe->qgeneratebase = skinframe->qhascolormapping;
5527         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
5528
5529         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
5530         //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]);
5531
5532         return skinframe;
5533 }
5534
5535 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
5536 {
5537         int width;
5538         int height;
5539         unsigned char *skindata;
5540
5541         if (!skinframe->qpixels)
5542                 return;
5543
5544         if (!skinframe->qhascolormapping)
5545                 colormapped = false;
5546
5547         if (colormapped)
5548         {
5549                 if (!skinframe->qgeneratebase)
5550                         return;
5551         }
5552         else
5553         {
5554                 if (!skinframe->qgeneratemerged)
5555                         return;
5556         }
5557
5558         width = skinframe->qwidth;
5559         height = skinframe->qheight;
5560         skindata = skinframe->qpixels;
5561
5562         if (skinframe->qgeneratenmap)
5563         {
5564                 unsigned char *temp1, *temp2;
5565                 skinframe->qgeneratenmap = false;
5566                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5567                 temp2 = temp1 + width * height * 4;
5568                 // use either a custom palette or the quake palette
5569                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
5570                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5571                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5572                 Mem_Free(temp1);
5573         }
5574
5575         if (skinframe->qgenerateglow)
5576         {
5577                 skinframe->qgenerateglow = false;
5578                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
5579         }
5580
5581         if (colormapped)
5582         {
5583                 skinframe->qgeneratebase = false;
5584                 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);
5585                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
5586                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
5587         }
5588         else
5589         {
5590                 skinframe->qgeneratemerged = false;
5591                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
5592         }
5593
5594         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
5595         {
5596                 Mem_Free(skinframe->qpixels);
5597                 skinframe->qpixels = NULL;
5598         }
5599 }
5600
5601 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)
5602 {
5603         int i;
5604         skinframe_t *skinframe;
5605
5606         if (cls.state == ca_dedicated)
5607                 return NULL;
5608
5609         // if already loaded just return it, otherwise make a new skinframe
5610         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5611         if (skinframe && skinframe->base)
5612                 return skinframe;
5613
5614         skinframe->stain = NULL;
5615         skinframe->merged = NULL;
5616         skinframe->base = NULL;
5617         skinframe->pants = NULL;
5618         skinframe->shirt = NULL;
5619         skinframe->nmap = NULL;
5620         skinframe->gloss = NULL;
5621         skinframe->glow = NULL;
5622         skinframe->fog = NULL;
5623         skinframe->hasalpha = false;
5624
5625         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5626         if (!skindata)
5627                 return NULL;
5628
5629         if (developer_loading.integer)
5630                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
5631
5632         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
5633         if (textureflags & TEXF_ALPHA)
5634         {
5635                 for (i = 0;i < width * height;i++)
5636                 {
5637                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
5638                         {
5639                                 skinframe->hasalpha = true;
5640                                 break;
5641                         }
5642                 }
5643                 if (r_loadfog && skinframe->hasalpha)
5644                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
5645         }
5646
5647         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
5648         //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]);
5649
5650         return skinframe;
5651 }
5652
5653 skinframe_t *R_SkinFrame_LoadMissing(void)
5654 {
5655         skinframe_t *skinframe;
5656
5657         if (cls.state == ca_dedicated)
5658                 return NULL;
5659
5660         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
5661         skinframe->stain = NULL;
5662         skinframe->merged = NULL;
5663         skinframe->base = NULL;
5664         skinframe->pants = NULL;
5665         skinframe->shirt = NULL;
5666         skinframe->nmap = NULL;
5667         skinframe->gloss = NULL;
5668         skinframe->glow = NULL;
5669         skinframe->fog = NULL;
5670         skinframe->hasalpha = false;
5671
5672         skinframe->avgcolor[0] = rand() / RAND_MAX;
5673         skinframe->avgcolor[1] = rand() / RAND_MAX;
5674         skinframe->avgcolor[2] = rand() / RAND_MAX;
5675         skinframe->avgcolor[3] = 1;
5676
5677         return skinframe;
5678 }
5679
5680 void R_Main_FreeViewCache(void)
5681 {
5682         if (r_refdef.viewcache.entityvisible)
5683                 Mem_Free(r_refdef.viewcache.entityvisible);
5684         if (r_refdef.viewcache.world_pvsbits)
5685                 Mem_Free(r_refdef.viewcache.world_pvsbits);
5686         if (r_refdef.viewcache.world_leafvisible)
5687                 Mem_Free(r_refdef.viewcache.world_leafvisible);
5688         if (r_refdef.viewcache.world_surfacevisible)
5689                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
5690         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
5691 }
5692
5693 void R_Main_ResizeViewCache(void)
5694 {
5695         int numentities = r_refdef.scene.numentities;
5696         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
5697         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
5698         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
5699         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
5700         if (r_refdef.viewcache.maxentities < numentities)
5701         {
5702                 r_refdef.viewcache.maxentities = numentities;
5703                 if (r_refdef.viewcache.entityvisible)
5704                         Mem_Free(r_refdef.viewcache.entityvisible);
5705                 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
5706         }
5707         if (r_refdef.viewcache.world_numclusters != numclusters)
5708         {
5709                 r_refdef.viewcache.world_numclusters = numclusters;
5710                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
5711                 if (r_refdef.viewcache.world_pvsbits)
5712                         Mem_Free(r_refdef.viewcache.world_pvsbits);
5713                 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
5714         }
5715         if (r_refdef.viewcache.world_numleafs != numleafs)
5716         {
5717                 r_refdef.viewcache.world_numleafs = numleafs;
5718                 if (r_refdef.viewcache.world_leafvisible)
5719                         Mem_Free(r_refdef.viewcache.world_leafvisible);
5720                 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
5721         }
5722         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
5723         {
5724                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
5725                 if (r_refdef.viewcache.world_surfacevisible)
5726                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
5727                 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
5728         }
5729 }
5730
5731 extern rtexture_t *loadingscreentexture;
5732 void gl_main_start(void)
5733 {
5734         loadingscreentexture = NULL;
5735         r_texture_blanknormalmap = NULL;
5736         r_texture_white = NULL;
5737         r_texture_grey128 = NULL;
5738         r_texture_black = NULL;
5739         r_texture_whitecube = NULL;
5740         r_texture_normalizationcube = NULL;
5741         r_texture_fogattenuation = NULL;
5742         r_texture_gammaramps = NULL;
5743
5744         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
5745         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
5746
5747         switch(vid.renderpath)
5748         {
5749         case RENDERPATH_GL20:
5750         case RENDERPATH_CGGL:
5751                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5752                 Cvar_SetValueQuick(&gl_combine, 1);
5753                 Cvar_SetValueQuick(&r_glsl, 1);
5754                 r_loadnormalmap = true;
5755                 r_loadgloss = true;
5756                 r_loadfog = false;
5757                 break;
5758         case RENDERPATH_GL13:
5759                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5760                 Cvar_SetValueQuick(&gl_combine, 1);
5761                 Cvar_SetValueQuick(&r_glsl, 0);
5762                 r_loadnormalmap = false;
5763                 r_loadgloss = false;
5764                 r_loadfog = true;
5765                 break;
5766         case RENDERPATH_GL11:
5767                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5768                 Cvar_SetValueQuick(&gl_combine, 0);
5769                 Cvar_SetValueQuick(&r_glsl, 0);
5770                 r_loadnormalmap = false;
5771                 r_loadgloss = false;
5772                 r_loadfog = true;
5773                 break;
5774         }
5775
5776         R_AnimCache_Free();
5777         R_FrameData_Reset();
5778
5779         r_numqueries = 0;
5780         r_maxqueries = 0;
5781         memset(r_queries, 0, sizeof(r_queries));
5782
5783         r_qwskincache = NULL;
5784         r_qwskincache_size = 0;
5785
5786         // set up r_skinframe loading system for textures
5787         memset(&r_skinframe, 0, sizeof(r_skinframe));
5788         r_skinframe.loadsequence = 1;
5789         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
5790
5791         r_main_texturepool = R_AllocTexturePool();
5792         R_BuildBlankTextures();
5793         R_BuildNoTexture();
5794         if (vid.support.arb_texture_cube_map)
5795         {
5796                 R_BuildWhiteCube();
5797                 R_BuildNormalizationCube();
5798         }
5799         r_texture_fogattenuation = NULL;
5800         r_texture_gammaramps = NULL;
5801         //r_texture_fogintensity = NULL;
5802         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
5803         memset(&r_waterstate, 0, sizeof(r_waterstate));
5804         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5805         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
5806         glslshaderstring = NULL;
5807 #ifdef SUPPORTCG
5808         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5809         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
5810         cgshaderstring = NULL;
5811 #endif
5812         memset(&r_svbsp, 0, sizeof (r_svbsp));
5813
5814         r_refdef.fogmasktable_density = 0;
5815 }
5816
5817 void gl_main_shutdown(void)
5818 {
5819         R_AnimCache_Free();
5820         R_FrameData_Reset();
5821
5822         R_Main_FreeViewCache();
5823
5824         if (r_maxqueries)
5825                 qglDeleteQueriesARB(r_maxqueries, r_queries);
5826
5827         r_numqueries = 0;
5828         r_maxqueries = 0;
5829         memset(r_queries, 0, sizeof(r_queries));
5830
5831         r_qwskincache = NULL;
5832         r_qwskincache_size = 0;
5833
5834         // clear out the r_skinframe state
5835         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
5836         memset(&r_skinframe, 0, sizeof(r_skinframe));
5837
5838         if (r_svbsp.nodes)
5839                 Mem_Free(r_svbsp.nodes);
5840         memset(&r_svbsp, 0, sizeof (r_svbsp));
5841         R_FreeTexturePool(&r_main_texturepool);
5842         loadingscreentexture = NULL;
5843         r_texture_blanknormalmap = NULL;
5844         r_texture_white = NULL;
5845         r_texture_grey128 = NULL;
5846         r_texture_black = NULL;
5847         r_texture_whitecube = NULL;
5848         r_texture_normalizationcube = NULL;
5849         r_texture_fogattenuation = NULL;
5850         r_texture_gammaramps = NULL;
5851         //r_texture_fogintensity = NULL;
5852         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
5853         memset(&r_waterstate, 0, sizeof(r_waterstate));
5854         R_GLSL_Restart_f();
5855 }
5856
5857 extern void CL_ParseEntityLump(char *entitystring);
5858 void gl_main_newmap(void)
5859 {
5860         // FIXME: move this code to client
5861         int l;
5862         char *entities, entname[MAX_QPATH];
5863         if (r_qwskincache)
5864                 Mem_Free(r_qwskincache);
5865         r_qwskincache = NULL;
5866         r_qwskincache_size = 0;
5867         if (cl.worldmodel)
5868         {
5869                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
5870                 l = (int)strlen(entname) - 4;
5871                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
5872                 {
5873                         memcpy(entname + l, ".ent", 5);
5874                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
5875                         {
5876                                 CL_ParseEntityLump(entities);
5877                                 Mem_Free(entities);
5878                                 return;
5879                         }
5880                 }
5881                 if (cl.worldmodel->brush.entities)
5882                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
5883         }
5884         R_Main_FreeViewCache();
5885
5886         R_FrameData_Reset();
5887 }
5888
5889 void GL_Main_Init(void)
5890 {
5891         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
5892
5893         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
5894         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
5895         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
5896         if (gamemode == GAME_NEHAHRA)
5897         {
5898                 Cvar_RegisterVariable (&gl_fogenable);
5899                 Cvar_RegisterVariable (&gl_fogdensity);
5900                 Cvar_RegisterVariable (&gl_fogred);
5901                 Cvar_RegisterVariable (&gl_foggreen);
5902                 Cvar_RegisterVariable (&gl_fogblue);
5903                 Cvar_RegisterVariable (&gl_fogstart);
5904                 Cvar_RegisterVariable (&gl_fogend);
5905                 Cvar_RegisterVariable (&gl_skyclip);
5906         }
5907         Cvar_RegisterVariable(&r_motionblur);
5908         Cvar_RegisterVariable(&r_motionblur_maxblur);
5909         Cvar_RegisterVariable(&r_motionblur_bmin);
5910         Cvar_RegisterVariable(&r_motionblur_vmin);
5911         Cvar_RegisterVariable(&r_motionblur_vmax);
5912         Cvar_RegisterVariable(&r_motionblur_vcoeff);
5913         Cvar_RegisterVariable(&r_motionblur_randomize);
5914         Cvar_RegisterVariable(&r_damageblur);
5915         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
5916         Cvar_RegisterVariable(&r_equalize_entities_minambient);
5917         Cvar_RegisterVariable(&r_equalize_entities_by);
5918         Cvar_RegisterVariable(&r_equalize_entities_to);
5919         Cvar_RegisterVariable(&r_depthfirst);
5920         Cvar_RegisterVariable(&r_useinfinitefarclip);
5921         Cvar_RegisterVariable(&r_farclip_base);
5922         Cvar_RegisterVariable(&r_farclip_world);
5923         Cvar_RegisterVariable(&r_nearclip);
5924         Cvar_RegisterVariable(&r_showbboxes);
5925         Cvar_RegisterVariable(&r_showsurfaces);
5926         Cvar_RegisterVariable(&r_showtris);
5927         Cvar_RegisterVariable(&r_shownormals);
5928         Cvar_RegisterVariable(&r_showlighting);
5929         Cvar_RegisterVariable(&r_showshadowvolumes);
5930         Cvar_RegisterVariable(&r_showcollisionbrushes);
5931         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
5932         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
5933         Cvar_RegisterVariable(&r_showdisabledepthtest);
5934         Cvar_RegisterVariable(&r_drawportals);
5935         Cvar_RegisterVariable(&r_drawentities);
5936         Cvar_RegisterVariable(&r_cullentities_trace);
5937         Cvar_RegisterVariable(&r_cullentities_trace_samples);
5938         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
5939         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
5940         Cvar_RegisterVariable(&r_cullentities_trace_delay);
5941         Cvar_RegisterVariable(&r_drawviewmodel);
5942         Cvar_RegisterVariable(&r_speeds);
5943         Cvar_RegisterVariable(&r_fullbrights);
5944         Cvar_RegisterVariable(&r_wateralpha);
5945         Cvar_RegisterVariable(&r_dynamic);
5946         Cvar_RegisterVariable(&r_fullbright);
5947         Cvar_RegisterVariable(&r_shadows);
5948         Cvar_RegisterVariable(&r_shadows_darken);
5949         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
5950         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
5951         Cvar_RegisterVariable(&r_shadows_throwdistance);
5952         Cvar_RegisterVariable(&r_shadows_throwdirection);
5953         Cvar_RegisterVariable(&r_q1bsp_skymasking);
5954         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
5955         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
5956         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
5957         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
5958         Cvar_RegisterVariable(&r_fog_exp2);
5959         Cvar_RegisterVariable(&r_drawfog);
5960         Cvar_RegisterVariable(&r_transparentdepthmasking);
5961         Cvar_RegisterVariable(&r_texture_dds_load);
5962         Cvar_RegisterVariable(&r_texture_dds_save);
5963         Cvar_RegisterVariable(&r_textureunits);
5964         Cvar_RegisterVariable(&gl_combine);
5965         Cvar_RegisterVariable(&r_glsl);
5966         Cvar_RegisterVariable(&r_glsl_deluxemapping);
5967         Cvar_RegisterVariable(&r_glsl_offsetmapping);
5968         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
5969         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
5970         Cvar_RegisterVariable(&r_glsl_postprocess);
5971         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
5972         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
5973         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
5974         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
5975         Cvar_RegisterVariable(&r_water);
5976         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
5977         Cvar_RegisterVariable(&r_water_clippingplanebias);
5978         Cvar_RegisterVariable(&r_water_refractdistort);
5979         Cvar_RegisterVariable(&r_water_reflectdistort);
5980         Cvar_RegisterVariable(&r_lerpsprites);
5981         Cvar_RegisterVariable(&r_lerpmodels);
5982         Cvar_RegisterVariable(&r_lerplightstyles);
5983         Cvar_RegisterVariable(&r_waterscroll);
5984         Cvar_RegisterVariable(&r_bloom);
5985         Cvar_RegisterVariable(&r_bloom_colorscale);
5986         Cvar_RegisterVariable(&r_bloom_brighten);
5987         Cvar_RegisterVariable(&r_bloom_blur);
5988         Cvar_RegisterVariable(&r_bloom_resolution);
5989         Cvar_RegisterVariable(&r_bloom_colorexponent);
5990         Cvar_RegisterVariable(&r_bloom_colorsubtract);
5991         Cvar_RegisterVariable(&r_hdr);
5992         Cvar_RegisterVariable(&r_hdr_scenebrightness);
5993         Cvar_RegisterVariable(&r_hdr_glowintensity);
5994         Cvar_RegisterVariable(&r_hdr_range);
5995         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
5996         Cvar_RegisterVariable(&developer_texturelogging);
5997         Cvar_RegisterVariable(&gl_lightmaps);
5998         Cvar_RegisterVariable(&r_test);
5999         Cvar_RegisterVariable(&r_batchmode);
6000         Cvar_RegisterVariable(&r_glsl_saturation);
6001         Cvar_RegisterVariable(&r_framedatasize);
6002         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
6003                 Cvar_SetValue("r_fullbrights", 0);
6004         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
6005
6006         Cvar_RegisterVariable(&r_track_sprites);
6007         Cvar_RegisterVariable(&r_track_sprites_flags);
6008         Cvar_RegisterVariable(&r_track_sprites_scalew);
6009         Cvar_RegisterVariable(&r_track_sprites_scaleh);
6010         Cvar_RegisterVariable(&r_overheadsprites_perspective);
6011         Cvar_RegisterVariable(&r_overheadsprites_pushback);
6012 }
6013
6014 extern void R_Textures_Init(void);
6015 extern void GL_Draw_Init(void);
6016 extern void GL_Main_Init(void);
6017 extern void R_Shadow_Init(void);
6018 extern void R_Sky_Init(void);
6019 extern void GL_Surf_Init(void);
6020 extern void R_Particles_Init(void);
6021 extern void R_Explosion_Init(void);
6022 extern void gl_backend_init(void);
6023 extern void Sbar_Init(void);
6024 extern void R_LightningBeams_Init(void);
6025 extern void Mod_RenderInit(void);
6026 extern void Font_Init(void);
6027
6028 void Render_Init(void)
6029 {
6030         gl_backend_init();
6031         R_Textures_Init();
6032         GL_Main_Init();
6033         Font_Init();
6034         GL_Draw_Init();
6035         R_Shadow_Init();
6036         R_Sky_Init();
6037         GL_Surf_Init();
6038         Sbar_Init();
6039         R_Particles_Init();
6040         R_Explosion_Init();
6041         R_LightningBeams_Init();
6042         Mod_RenderInit();
6043 }
6044
6045 /*
6046 ===============
6047 GL_Init
6048 ===============
6049 */
6050 extern char *ENGINE_EXTENSIONS;
6051 void GL_Init (void)
6052 {
6053         gl_renderer = (const char *)qglGetString(GL_RENDERER);
6054         gl_vendor = (const char *)qglGetString(GL_VENDOR);
6055         gl_version = (const char *)qglGetString(GL_VERSION);
6056         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
6057
6058         if (!gl_extensions)
6059                 gl_extensions = "";
6060         if (!gl_platformextensions)
6061                 gl_platformextensions = "";
6062
6063         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
6064         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
6065         Con_Printf("GL_VERSION: %s\n", gl_version);
6066         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
6067         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
6068
6069         VID_CheckExtensions();
6070
6071         // LordHavoc: report supported extensions
6072         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
6073
6074         // clear to black (loading plaque will be seen over this)
6075         CHECKGLERROR
6076         qglClearColor(0,0,0,1);CHECKGLERROR
6077         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
6078 }
6079
6080 int R_CullBox(const vec3_t mins, const vec3_t maxs)
6081 {
6082         int i;
6083         mplane_t *p;
6084         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6085         {
6086                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
6087                 if (i == 4)
6088                         continue;
6089                 p = r_refdef.view.frustum + i;
6090                 switch(p->signbits)
6091                 {
6092                 default:
6093                 case 0:
6094                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6095                                 return true;
6096                         break;
6097                 case 1:
6098                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6099                                 return true;
6100                         break;
6101                 case 2:
6102                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6103                                 return true;
6104                         break;
6105                 case 3:
6106                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6107                                 return true;
6108                         break;
6109                 case 4:
6110                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6111                                 return true;
6112                         break;
6113                 case 5:
6114                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6115                                 return true;
6116                         break;
6117                 case 6:
6118                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6119                                 return true;
6120                         break;
6121                 case 7:
6122                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6123                                 return true;
6124                         break;
6125                 }
6126         }
6127         return false;
6128 }
6129
6130 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
6131 {
6132         int i;
6133         const mplane_t *p;
6134         for (i = 0;i < numplanes;i++)
6135         {
6136                 p = planes + i;
6137                 switch(p->signbits)
6138                 {
6139                 default:
6140                 case 0:
6141                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6142                                 return true;
6143                         break;
6144                 case 1:
6145                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6146                                 return true;
6147                         break;
6148                 case 2:
6149                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6150                                 return true;
6151                         break;
6152                 case 3:
6153                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6154                                 return true;
6155                         break;
6156                 case 4:
6157                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6158                                 return true;
6159                         break;
6160                 case 5:
6161                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6162                                 return true;
6163                         break;
6164                 case 6:
6165                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6166                                 return true;
6167                         break;
6168                 case 7:
6169                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6170                                 return true;
6171                         break;
6172                 }
6173         }
6174         return false;
6175 }
6176
6177 //==================================================================================
6178
6179 // LordHavoc: this stores temporary data used within the same frame
6180
6181 qboolean r_framedata_failed;
6182 static size_t r_framedata_size;
6183 static size_t r_framedata_current;
6184 static void *r_framedata_base;
6185
6186 void R_FrameData_Reset(void)
6187 {
6188         if (r_framedata_base)
6189                 Mem_Free(r_framedata_base);
6190         r_framedata_base = NULL;
6191         r_framedata_size = 0;
6192         r_framedata_current = 0;
6193         r_framedata_failed = false;
6194 }
6195
6196 void R_FrameData_NewFrame(void)
6197 {
6198         size_t wantedsize;
6199         if (r_framedata_failed)
6200                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
6201         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
6202         wantedsize = bound(65536, wantedsize, 128*1024*1024);
6203         if (r_framedata_size != wantedsize)
6204         {
6205                 r_framedata_size = wantedsize;
6206                 if (r_framedata_base)
6207                         Mem_Free(r_framedata_base);
6208                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
6209         }
6210         r_framedata_current = 0;
6211         r_framedata_failed = false;
6212 }
6213
6214 void *R_FrameData_Alloc(size_t size)
6215 {
6216         void *data;
6217
6218         // align to 16 byte boundary
6219         size = (size + 15) & ~15;
6220         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
6221         r_framedata_current += size;
6222
6223         // check overflow
6224         if (r_framedata_current > r_framedata_size)
6225                 r_framedata_failed = true;
6226
6227         // return NULL on everything after a failure
6228         if (r_framedata_failed)
6229                 return NULL;
6230
6231         return data;
6232 }
6233
6234 void *R_FrameData_Store(size_t size, void *data)
6235 {
6236         void *d = R_FrameData_Alloc(size);
6237         if (d)
6238                 memcpy(d, data, size);
6239         return d;
6240 }
6241
6242 //==================================================================================
6243
6244 // LordHavoc: animcache originally written by Echon, rewritten since then
6245
6246 /**
6247  * Animation cache prevents re-generating mesh data for an animated model
6248  * multiple times in one frame for lighting, shadowing, reflections, etc.
6249  */
6250
6251 void R_AnimCache_Free(void)
6252 {
6253 }
6254
6255 void R_AnimCache_ClearCache(void)
6256 {
6257         int i;
6258         entity_render_t *ent;
6259
6260         for (i = 0;i < r_refdef.scene.numentities;i++)
6261         {
6262                 ent = r_refdef.scene.entities[i];
6263                 ent->animcache_vertex3f = NULL;
6264                 ent->animcache_normal3f = NULL;
6265                 ent->animcache_svector3f = NULL;
6266                 ent->animcache_tvector3f = NULL;
6267         }
6268 }
6269
6270 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6271 {
6272         dp_model_t *model = ent->model;
6273         int numvertices;
6274         // see if it's already cached this frame
6275         if (ent->animcache_vertex3f)
6276         {
6277                 // add normals/tangents if needed
6278                 if (wantnormals || wanttangents)
6279                 {
6280                         if (ent->animcache_normal3f)
6281                                 wantnormals = false;
6282                         if (ent->animcache_svector3f)
6283                                 wanttangents = false;
6284                         if (wantnormals || wanttangents)
6285                         {
6286                                 numvertices = model->surfmesh.num_vertices;
6287                                 if (wantnormals)
6288                                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6289                                 if (wanttangents)
6290                                 {
6291                                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6292                                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6293                                 }
6294                                 if (!r_framedata_failed)
6295                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
6296                         }
6297                 }
6298         }
6299         else
6300         {
6301                 // see if this ent is worth caching
6302                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
6303                         return false;
6304                 // get some memory for this entity and generate mesh data
6305                 numvertices = model->surfmesh.num_vertices;
6306                 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6307                 if (wantnormals)
6308                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6309                 if (wanttangents)
6310                 {
6311                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6312                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6313                 }
6314                 if (!r_framedata_failed)
6315                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
6316         }
6317         return !r_framedata_failed;
6318 }
6319
6320 void R_AnimCache_CacheVisibleEntities(void)
6321 {
6322         int i;
6323         qboolean wantnormals = !r_showsurfaces.integer;
6324         qboolean wanttangents = !r_showsurfaces.integer;
6325
6326         switch(vid.renderpath)
6327         {
6328         case RENDERPATH_GL20:
6329         case RENDERPATH_CGGL:
6330                 break;
6331         case RENDERPATH_GL13:
6332         case RENDERPATH_GL11:
6333                 wanttangents = false;
6334                 break;
6335         }
6336
6337         // TODO: thread this
6338         // NOTE: R_PrepareRTLights() also caches entities
6339
6340         for (i = 0;i < r_refdef.scene.numentities;i++)
6341                 if (r_refdef.viewcache.entityvisible[i])
6342                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
6343
6344         if (r_shadows.integer)
6345                 for (i = 0;i < r_refdef.scene.numentities;i++)
6346                         if (!r_refdef.viewcache.entityvisible[i])
6347                                 R_AnimCache_GetEntity(r_refdef.scene.entities[i], false, false);
6348 }
6349
6350 //==================================================================================
6351
6352 static void R_View_UpdateEntityLighting (void)
6353 {
6354         int i;
6355         entity_render_t *ent;
6356         vec3_t tempdiffusenormal, avg;
6357         vec_t f, fa, fd, fdd;
6358
6359         for (i = 0;i < r_refdef.scene.numentities;i++)
6360         {
6361                 ent = r_refdef.scene.entities[i];
6362
6363                 // skip unseen models
6364                 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
6365                         continue;
6366
6367                 // skip bsp models
6368                 if (ent->model && ent->model->brush.num_leafs)
6369                 {
6370                         // TODO: use modellight for r_ambient settings on world?
6371                         VectorSet(ent->modellight_ambient, 0, 0, 0);
6372                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
6373                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
6374                         continue;
6375                 }
6376
6377                 // fetch the lighting from the worldmodel data
6378                 VectorClear(ent->modellight_ambient);
6379                 VectorClear(ent->modellight_diffuse);
6380                 VectorClear(tempdiffusenormal);
6381                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
6382                 {
6383                         vec3_t org;
6384                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6385                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
6386                         if(ent->flags & RENDER_EQUALIZE)
6387                         {
6388                                 // first fix up ambient lighting...
6389                                 if(r_equalize_entities_minambient.value > 0)
6390                                 {
6391                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
6392                                         if(fd > 0)
6393                                         {
6394                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
6395                                                 if(fa < r_equalize_entities_minambient.value * fd)
6396                                                 {
6397                                                         // solve:
6398                                                         //   fa'/fd' = minambient
6399                                                         //   fa'+0.25*fd' = fa+0.25*fd
6400                                                         //   ...
6401                                                         //   fa' = fd' * minambient
6402                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
6403                                                         //   ...
6404                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
6405                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
6406                                                         //   ...
6407                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
6408                                                         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
6409                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
6410                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6411                                                 }
6412                                         }
6413                                 }
6414
6415                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
6416                                 {
6417                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
6418                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
6419                                         if(f > 0)
6420                                         {
6421                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
6422                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
6423                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6424                                         }
6425                                 }
6426                         }
6427                 }
6428                 else // highly rare
6429                         VectorSet(ent->modellight_ambient, 1, 1, 1);
6430
6431                 // move the light direction into modelspace coordinates for lighting code
6432                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
6433                 if(VectorLength2(ent->modellight_lightdir) == 0)
6434                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
6435                 VectorNormalize(ent->modellight_lightdir);
6436         }
6437 }
6438
6439 #define MAX_LINEOFSIGHTTRACES 64
6440
6441 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
6442 {
6443         int i;
6444         vec3_t boxmins, boxmaxs;
6445         vec3_t start;
6446         vec3_t end;
6447         dp_model_t *model = r_refdef.scene.worldmodel;
6448
6449         if (!model || !model->brush.TraceLineOfSight)
6450                 return true;
6451
6452         // expand the box a little
6453         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
6454         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
6455         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
6456         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
6457         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
6458         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
6459
6460         // try center
6461         VectorCopy(eye, start);
6462         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
6463         if (model->brush.TraceLineOfSight(model, start, end))
6464                 return true;
6465
6466         // try various random positions
6467         for (i = 0;i < numsamples;i++)
6468         {
6469                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
6470                 if (model->brush.TraceLineOfSight(model, start, end))
6471                         return true;
6472         }
6473
6474         return false;
6475 }
6476
6477
6478 static void R_View_UpdateEntityVisible (void)
6479 {
6480         int i;
6481         int renderimask;
6482         int samples;
6483         entity_render_t *ent;
6484
6485         renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
6486         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
6487         {
6488                 // worldmodel can check visibility
6489                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
6490                 for (i = 0;i < r_refdef.scene.numentities;i++)
6491                 {
6492                         ent = r_refdef.scene.entities[i];
6493                         if (!(ent->flags & renderimask))
6494                         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)))
6495                         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))
6496                                 r_refdef.viewcache.entityvisible[i] = true;
6497                 }
6498                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
6499                 {
6500                         for (i = 0;i < r_refdef.scene.numentities;i++)
6501                         {
6502                                 ent = r_refdef.scene.entities[i];
6503                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
6504                                 {
6505                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
6506                                         if (samples < 0)
6507                                                 continue; // temp entities do pvs only
6508                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
6509                                                 ent->last_trace_visibility = realtime;
6510                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
6511                                                 r_refdef.viewcache.entityvisible[i] = 0;
6512                                 }
6513                         }
6514                 }
6515         }
6516         else
6517         {
6518                 // no worldmodel or it can't check visibility
6519                 for (i = 0;i < r_refdef.scene.numentities;i++)
6520                 {
6521                         ent = r_refdef.scene.entities[i];
6522                         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));
6523                 }
6524         }
6525 }
6526
6527 /// only used if skyrendermasked, and normally returns false
6528 int R_DrawBrushModelsSky (void)
6529 {
6530         int i, sky;
6531         entity_render_t *ent;
6532
6533         sky = false;
6534         for (i = 0;i < r_refdef.scene.numentities;i++)
6535         {
6536                 if (!r_refdef.viewcache.entityvisible[i])
6537                         continue;
6538                 ent = r_refdef.scene.entities[i];
6539                 if (!ent->model || !ent->model->DrawSky)
6540                         continue;
6541                 ent->model->DrawSky(ent);
6542                 sky = true;
6543         }
6544         return sky;
6545 }
6546
6547 static void R_DrawNoModel(entity_render_t *ent);
6548 static void R_DrawModels(void)
6549 {
6550         int i;
6551         entity_render_t *ent;
6552
6553         for (i = 0;i < r_refdef.scene.numentities;i++)
6554         {
6555                 if (!r_refdef.viewcache.entityvisible[i])
6556                         continue;
6557                 ent = r_refdef.scene.entities[i];
6558                 r_refdef.stats.entities++;
6559                 if (ent->model && ent->model->Draw != NULL)
6560                         ent->model->Draw(ent);
6561                 else
6562                         R_DrawNoModel(ent);
6563         }
6564 }
6565
6566 static void R_DrawModelsDepth(void)
6567 {
6568         int i;
6569         entity_render_t *ent;
6570
6571         for (i = 0;i < r_refdef.scene.numentities;i++)
6572         {
6573                 if (!r_refdef.viewcache.entityvisible[i])
6574                         continue;
6575                 ent = r_refdef.scene.entities[i];
6576                 if (ent->model && ent->model->DrawDepth != NULL)
6577                         ent->model->DrawDepth(ent);
6578         }
6579 }
6580
6581 static void R_DrawModelsDebug(void)
6582 {
6583         int i;
6584         entity_render_t *ent;
6585
6586         for (i = 0;i < r_refdef.scene.numentities;i++)
6587         {
6588                 if (!r_refdef.viewcache.entityvisible[i])
6589                         continue;
6590                 ent = r_refdef.scene.entities[i];
6591                 if (ent->model && ent->model->DrawDebug != NULL)
6592                         ent->model->DrawDebug(ent);
6593         }
6594 }
6595
6596 static void R_DrawModelsAddWaterPlanes(void)
6597 {
6598         int i;
6599         entity_render_t *ent;
6600
6601         for (i = 0;i < r_refdef.scene.numentities;i++)
6602         {
6603                 if (!r_refdef.viewcache.entityvisible[i])
6604                         continue;
6605                 ent = r_refdef.scene.entities[i];
6606                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
6607                         ent->model->DrawAddWaterPlanes(ent);
6608         }
6609 }
6610
6611 static void R_View_SetFrustum(void)
6612 {
6613         int i;
6614         double slopex, slopey;
6615         vec3_t forward, left, up, origin;
6616
6617         // we can't trust r_refdef.view.forward and friends in reflected scenes
6618         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
6619
6620 #if 0
6621         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
6622         r_refdef.view.frustum[0].normal[1] = 0 - 0;
6623         r_refdef.view.frustum[0].normal[2] = -1 - 0;
6624         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
6625         r_refdef.view.frustum[1].normal[1] = 0 + 0;
6626         r_refdef.view.frustum[1].normal[2] = -1 + 0;
6627         r_refdef.view.frustum[2].normal[0] = 0 - 0;
6628         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
6629         r_refdef.view.frustum[2].normal[2] = -1 - 0;
6630         r_refdef.view.frustum[3].normal[0] = 0 + 0;
6631         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
6632         r_refdef.view.frustum[3].normal[2] = -1 + 0;
6633 #endif
6634
6635 #if 0
6636         zNear = r_refdef.nearclip;
6637         nudge = 1.0 - 1.0 / (1<<23);
6638         r_refdef.view.frustum[4].normal[0] = 0 - 0;
6639         r_refdef.view.frustum[4].normal[1] = 0 - 0;
6640         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
6641         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
6642         r_refdef.view.frustum[5].normal[0] = 0 + 0;
6643         r_refdef.view.frustum[5].normal[1] = 0 + 0;
6644         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
6645         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
6646 #endif
6647
6648
6649
6650 #if 0
6651         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
6652         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
6653         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
6654         r_refdef.view.frustum[0].dist = m[15] - m[12];
6655
6656         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
6657         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
6658         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
6659         r_refdef.view.frustum[1].dist = m[15] + m[12];
6660
6661         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
6662         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
6663         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
6664         r_refdef.view.frustum[2].dist = m[15] - m[13];
6665
6666         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
6667         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
6668         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
6669         r_refdef.view.frustum[3].dist = m[15] + m[13];
6670
6671         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
6672         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
6673         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
6674         r_refdef.view.frustum[4].dist = m[15] - m[14];
6675
6676         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
6677         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
6678         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
6679         r_refdef.view.frustum[5].dist = m[15] + m[14];
6680 #endif
6681
6682         if (r_refdef.view.useperspective)
6683         {
6684                 slopex = 1.0 / r_refdef.view.frustum_x;
6685                 slopey = 1.0 / r_refdef.view.frustum_y;
6686                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
6687                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
6688                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
6689                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
6690                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6691
6692                 // Leaving those out was a mistake, those were in the old code, and they
6693                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
6694                 // I couldn't reproduce it after adding those normalizations. --blub
6695                 VectorNormalize(r_refdef.view.frustum[0].normal);
6696                 VectorNormalize(r_refdef.view.frustum[1].normal);
6697                 VectorNormalize(r_refdef.view.frustum[2].normal);
6698                 VectorNormalize(r_refdef.view.frustum[3].normal);
6699
6700                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
6701                 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]);
6702                 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]);
6703                 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]);
6704                 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]);
6705
6706                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
6707                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
6708                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
6709                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
6710                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6711         }
6712         else
6713         {
6714                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
6715                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
6716                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
6717                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
6718                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6719                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
6720                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
6721                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
6722                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
6723                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6724         }
6725         r_refdef.view.numfrustumplanes = 5;
6726
6727         if (r_refdef.view.useclipplane)
6728         {
6729                 r_refdef.view.numfrustumplanes = 6;
6730                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
6731         }
6732
6733         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6734                 PlaneClassify(r_refdef.view.frustum + i);
6735
6736         // LordHavoc: note to all quake engine coders, Quake had a special case
6737         // for 90 degrees which assumed a square view (wrong), so I removed it,
6738         // Quake2 has it disabled as well.
6739
6740         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
6741         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
6742         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
6743         //PlaneClassify(&frustum[0]);
6744
6745         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
6746         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
6747         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
6748         //PlaneClassify(&frustum[1]);
6749
6750         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
6751         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
6752         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
6753         //PlaneClassify(&frustum[2]);
6754
6755         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
6756         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
6757         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
6758         //PlaneClassify(&frustum[3]);
6759
6760         // nearclip plane
6761         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
6762         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
6763         //PlaneClassify(&frustum[4]);
6764 }
6765
6766 void R_View_Update(void)
6767 {
6768         R_Main_ResizeViewCache();
6769         R_View_SetFrustum();
6770         R_View_WorldVisibility(r_refdef.view.useclipplane);
6771         R_View_UpdateEntityVisible();
6772         R_View_UpdateEntityLighting();
6773 }
6774
6775 void R_SetupView(qboolean allowwaterclippingplane)
6776 {
6777         const float *customclipplane = NULL;
6778         float plane[4];
6779         if (r_refdef.view.useclipplane && allowwaterclippingplane)
6780         {
6781                 // LordHavoc: couldn't figure out how to make this approach the
6782                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
6783                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
6784                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
6785                         dist = r_refdef.view.clipplane.dist;
6786                 plane[0] = r_refdef.view.clipplane.normal[0];
6787                 plane[1] = r_refdef.view.clipplane.normal[1];
6788                 plane[2] = r_refdef.view.clipplane.normal[2];
6789                 plane[3] = dist;
6790                 customclipplane = plane;
6791         }
6792
6793         if (!r_refdef.view.useperspective)
6794                 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);
6795         else if (vid.stencil && r_useinfinitefarclip.integer)
6796                 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);
6797         else
6798                 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);
6799         R_SetViewport(&r_refdef.view.viewport);
6800 }
6801
6802 void R_EntityMatrix(const matrix4x4_t *matrix)
6803 {
6804         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
6805         {
6806                 gl_modelmatrixchanged = false;
6807                 gl_modelmatrix = *matrix;
6808                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
6809                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
6810                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
6811                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
6812                 CHECKGLERROR
6813                 switch(vid.renderpath)
6814                 {
6815                 case RENDERPATH_GL20:
6816                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
6817                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
6818                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6819                         break;
6820                 case RENDERPATH_CGGL:
6821 #ifdef SUPPORTCG
6822                         CHECKCGERROR
6823                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
6824                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
6825                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6826 #endif
6827                         break;
6828                 case RENDERPATH_GL13:
6829                 case RENDERPATH_GL11:
6830                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6831                         break;
6832                 }
6833         }
6834 }
6835
6836 void R_ResetViewRendering2D(void)
6837 {
6838         r_viewport_t viewport;
6839         DrawQ_Finish();
6840
6841         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
6842         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);
6843         R_SetViewport(&viewport);
6844         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
6845         GL_Color(1, 1, 1, 1);
6846         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6847         GL_BlendFunc(GL_ONE, GL_ZERO);
6848         GL_AlphaTest(false);
6849         GL_ScissorTest(false);
6850         GL_DepthMask(false);
6851         GL_DepthRange(0, 1);
6852         GL_DepthTest(false);
6853         R_EntityMatrix(&identitymatrix);
6854         R_Mesh_ResetTextureState();
6855         GL_PolygonOffset(0, 0);
6856         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
6857         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6858         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
6859         qglStencilMask(~0);CHECKGLERROR
6860         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
6861         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
6862         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
6863 }
6864
6865 void R_ResetViewRendering3D(void)
6866 {
6867         DrawQ_Finish();
6868
6869         R_SetupView(true);
6870         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6871         GL_Color(1, 1, 1, 1);
6872         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6873         GL_BlendFunc(GL_ONE, GL_ZERO);
6874         GL_AlphaTest(false);
6875         GL_ScissorTest(true);
6876         GL_DepthMask(true);
6877         GL_DepthRange(0, 1);
6878         GL_DepthTest(true);
6879         R_EntityMatrix(&identitymatrix);
6880         R_Mesh_ResetTextureState();
6881         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6882         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
6883         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6884         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
6885         qglStencilMask(~0);CHECKGLERROR
6886         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
6887         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
6888         GL_CullFace(r_refdef.view.cullface_back);
6889 }
6890
6891 void R_RenderScene(void);
6892 void R_RenderWaterPlanes(void);
6893
6894 static void R_Water_StartFrame(void)
6895 {
6896         int i;
6897         int waterwidth, waterheight, texturewidth, textureheight;
6898         r_waterstate_waterplane_t *p;
6899
6900         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
6901                 return;
6902
6903         switch(vid.renderpath)
6904         {
6905         case RENDERPATH_GL20:
6906         case RENDERPATH_CGGL:
6907                 break;
6908         case RENDERPATH_GL13:
6909         case RENDERPATH_GL11:
6910                 return;
6911         }
6912
6913         // set waterwidth and waterheight to the water resolution that will be
6914         // used (often less than the screen resolution for faster rendering)
6915         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
6916         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
6917
6918         // calculate desired texture sizes
6919         // can't use water if the card does not support the texture size
6920         if (!r_water.integer || r_showsurfaces.integer)
6921                 texturewidth = textureheight = waterwidth = waterheight = 0;
6922         else if (vid.support.arb_texture_non_power_of_two)
6923         {
6924                 texturewidth = waterwidth;
6925                 textureheight = waterheight;
6926         }
6927         else
6928         {
6929                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
6930                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
6931         }
6932
6933         // allocate textures as needed
6934         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
6935         {
6936                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
6937                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
6938                 {
6939                         if (p->texture_refraction)
6940                                 R_FreeTexture(p->texture_refraction);
6941                         p->texture_refraction = NULL;
6942                         if (p->texture_reflection)
6943                                 R_FreeTexture(p->texture_reflection);
6944                         p->texture_reflection = NULL;
6945                 }
6946                 memset(&r_waterstate, 0, sizeof(r_waterstate));
6947                 r_waterstate.texturewidth = texturewidth;
6948                 r_waterstate.textureheight = textureheight;
6949         }
6950
6951         if (r_waterstate.texturewidth)
6952         {
6953                 r_waterstate.enabled = true;
6954
6955                 // when doing a reduced render (HDR) we want to use a smaller area
6956                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
6957                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
6958
6959                 // set up variables that will be used in shader setup
6960                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
6961                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
6962                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
6963                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
6964         }
6965
6966         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
6967         r_waterstate.numwaterplanes = 0;
6968 }
6969
6970 void R_Water_AddWaterPlane(msurface_t *surface)
6971 {
6972         int triangleindex, planeindex;
6973         const int *e;
6974         vec3_t vert[3];
6975         vec3_t normal;
6976         vec3_t center;
6977         mplane_t plane;
6978         r_waterstate_waterplane_t *p;
6979         texture_t *t = R_GetCurrentTexture(surface->texture);
6980         // just use the first triangle with a valid normal for any decisions
6981         VectorClear(normal);
6982         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
6983         {
6984                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
6985                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
6986                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
6987                 TriangleNormal(vert[0], vert[1], vert[2], normal);
6988                 if (VectorLength2(normal) >= 0.001)
6989                         break;
6990         }
6991
6992         VectorCopy(normal, plane.normal);
6993         VectorNormalize(plane.normal);
6994         plane.dist = DotProduct(vert[0], plane.normal);
6995         PlaneClassify(&plane);
6996         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
6997         {
6998                 // skip backfaces (except if nocullface is set)
6999                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
7000                         return;
7001                 VectorNegate(plane.normal, plane.normal);
7002                 plane.dist *= -1;
7003                 PlaneClassify(&plane);
7004         }
7005
7006
7007         // find a matching plane if there is one
7008         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7009                 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
7010                         break;
7011         if (planeindex >= r_waterstate.maxwaterplanes)
7012                 return; // nothing we can do, out of planes
7013
7014         // if this triangle does not fit any known plane rendered this frame, add one
7015         if (planeindex >= r_waterstate.numwaterplanes)
7016         {
7017                 // store the new plane
7018                 r_waterstate.numwaterplanes++;
7019                 p->plane = plane;
7020                 // clear materialflags and pvs
7021                 p->materialflags = 0;
7022                 p->pvsvalid = false;
7023         }
7024         // merge this surface's materialflags into the waterplane
7025         p->materialflags |= t->currentmaterialflags;
7026         // merge this surface's PVS into the waterplane
7027         VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
7028         if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
7029          && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
7030         {
7031                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
7032                 p->pvsvalid = true;
7033         }
7034 }
7035
7036 static void R_Water_ProcessPlanes(void)
7037 {
7038         r_refdef_view_t originalview;
7039         r_refdef_view_t myview;
7040         int planeindex;
7041         r_waterstate_waterplane_t *p;
7042
7043         originalview = r_refdef.view;
7044
7045         // make sure enough textures are allocated
7046         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7047         {
7048                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7049                 {
7050                         if (!p->texture_refraction)
7051                                 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7052                         if (!p->texture_refraction)
7053                                 goto error;
7054                 }
7055
7056                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7057                 {
7058                         if (!p->texture_reflection)
7059                                 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7060                         if (!p->texture_reflection)
7061                                 goto error;
7062                 }
7063         }
7064
7065         // render views
7066         r_refdef.view = originalview;
7067         r_refdef.view.showdebug = false;
7068         r_refdef.view.width = r_waterstate.waterwidth;
7069         r_refdef.view.height = r_waterstate.waterheight;
7070         r_refdef.view.useclipplane = true;
7071         myview = r_refdef.view;
7072         r_waterstate.renderingscene = true;
7073         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7074         {
7075                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7076                 {
7077                         r_refdef.view = myview;
7078                         // render reflected scene and copy into texture
7079                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
7080                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
7081                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
7082                         r_refdef.view.clipplane = p->plane;
7083                         // reverse the cullface settings for this render
7084                         r_refdef.view.cullface_front = GL_FRONT;
7085                         r_refdef.view.cullface_back = GL_BACK;
7086                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
7087                         {
7088                                 r_refdef.view.usecustompvs = true;
7089                                 if (p->pvsvalid)
7090                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7091                                 else
7092                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7093                         }
7094
7095                         R_ResetViewRendering3D();
7096                         R_ClearScreen(r_refdef.fogenabled);
7097                         R_View_Update();
7098                         R_RenderScene();
7099
7100                         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);
7101                 }
7102
7103                 // render the normal view scene and copy into texture
7104                 // (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)
7105                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7106                 {
7107                         r_refdef.view = myview;
7108                         r_refdef.view.clipplane = p->plane;
7109                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
7110                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
7111                         PlaneClassify(&r_refdef.view.clipplane);
7112
7113                         R_ResetViewRendering3D();
7114                         R_ClearScreen(r_refdef.fogenabled);
7115                         R_View_Update();
7116                         R_RenderScene();
7117
7118                         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);
7119                 }
7120
7121         }
7122         r_waterstate.renderingscene = false;
7123         r_refdef.view = originalview;
7124         R_ResetViewRendering3D();
7125         R_ClearScreen(r_refdef.fogenabled);
7126         R_View_Update();
7127         return;
7128 error:
7129         r_refdef.view = originalview;
7130         r_waterstate.renderingscene = false;
7131         Cvar_SetValueQuick(&r_water, 0);
7132         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
7133         return;
7134 }
7135
7136 void R_Bloom_StartFrame(void)
7137 {
7138         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
7139
7140         switch(vid.renderpath)
7141         {
7142         case RENDERPATH_GL20:
7143         case RENDERPATH_CGGL:
7144                 break;
7145         case RENDERPATH_GL13:
7146         case RENDERPATH_GL11:
7147                 return;
7148         }
7149
7150         // set bloomwidth and bloomheight to the bloom resolution that will be
7151         // used (often less than the screen resolution for faster rendering)
7152         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
7153         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
7154         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
7155         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
7156         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
7157
7158         // calculate desired texture sizes
7159         if (vid.support.arb_texture_non_power_of_two)
7160         {
7161                 screentexturewidth = r_refdef.view.width;
7162                 screentextureheight = r_refdef.view.height;
7163                 bloomtexturewidth = r_bloomstate.bloomwidth;
7164                 bloomtextureheight = r_bloomstate.bloomheight;
7165         }
7166         else
7167         {
7168                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
7169                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
7170                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
7171                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
7172         }
7173
7174         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))
7175         {
7176                 Cvar_SetValueQuick(&r_hdr, 0);
7177                 Cvar_SetValueQuick(&r_bloom, 0);
7178                 Cvar_SetValueQuick(&r_motionblur, 0);
7179                 Cvar_SetValueQuick(&r_damageblur, 0);
7180         }
7181
7182         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)))
7183                 screentexturewidth = screentextureheight = 0;
7184         if (!r_hdr.integer && !r_bloom.integer)
7185                 bloomtexturewidth = bloomtextureheight = 0;
7186
7187         // allocate textures as needed
7188         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
7189         {
7190                 if (r_bloomstate.texture_screen)
7191                         R_FreeTexture(r_bloomstate.texture_screen);
7192                 r_bloomstate.texture_screen = NULL;
7193                 r_bloomstate.screentexturewidth = screentexturewidth;
7194                 r_bloomstate.screentextureheight = screentextureheight;
7195                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
7196                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
7197         }
7198         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
7199         {
7200                 if (r_bloomstate.texture_bloom)
7201                         R_FreeTexture(r_bloomstate.texture_bloom);
7202                 r_bloomstate.texture_bloom = NULL;
7203                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
7204                 r_bloomstate.bloomtextureheight = bloomtextureheight;
7205                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
7206                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7207         }
7208
7209         // when doing a reduced render (HDR) we want to use a smaller area
7210         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
7211         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
7212         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
7213         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
7214         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
7215
7216         // set up a texcoord array for the full resolution screen image
7217         // (we have to keep this around to copy back during final render)
7218         r_bloomstate.screentexcoord2f[0] = 0;
7219         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7220         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7221         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7222         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7223         r_bloomstate.screentexcoord2f[5] = 0;
7224         r_bloomstate.screentexcoord2f[6] = 0;
7225         r_bloomstate.screentexcoord2f[7] = 0;
7226
7227         // set up a texcoord array for the reduced resolution bloom image
7228         // (which will be additive blended over the screen image)
7229         r_bloomstate.bloomtexcoord2f[0] = 0;
7230         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7231         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7232         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7233         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7234         r_bloomstate.bloomtexcoord2f[5] = 0;
7235         r_bloomstate.bloomtexcoord2f[6] = 0;
7236         r_bloomstate.bloomtexcoord2f[7] = 0;
7237
7238         if (r_hdr.integer || r_bloom.integer)
7239         {
7240                 r_bloomstate.enabled = true;
7241                 r_bloomstate.hdr = r_hdr.integer != 0;
7242         }
7243
7244         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);
7245 }
7246
7247 void R_Bloom_CopyBloomTexture(float colorscale)
7248 {
7249         r_refdef.stats.bloom++;
7250
7251         // scale down screen texture to the bloom texture size
7252         CHECKGLERROR
7253         R_SetViewport(&r_bloomstate.viewport);
7254         GL_BlendFunc(GL_ONE, GL_ZERO);
7255         GL_Color(colorscale, colorscale, colorscale, 1);
7256         // TODO: optimize with multitexture or GLSL
7257         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7258         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7259         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7260         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7261
7262         // we now have a bloom image in the framebuffer
7263         // copy it into the bloom image texture for later processing
7264         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);
7265         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7266 }
7267
7268 void R_Bloom_CopyHDRTexture(void)
7269 {
7270         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);
7271         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7272 }
7273
7274 void R_Bloom_MakeTexture(void)
7275 {
7276         int x, range, dir;
7277         float xoffset, yoffset, r, brighten;
7278
7279         r_refdef.stats.bloom++;
7280
7281         R_ResetViewRendering2D();
7282         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7283         R_Mesh_ColorPointer(NULL, 0, 0);
7284
7285         // we have a bloom image in the framebuffer
7286         CHECKGLERROR
7287         R_SetViewport(&r_bloomstate.viewport);
7288
7289         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
7290         {
7291                 x *= 2;
7292                 r = bound(0, r_bloom_colorexponent.value / x, 1);
7293                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7294                 GL_Color(r, r, r, 1);
7295                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7296                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
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                 // copy the vertically blurred bloom view to a texture
7301                 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);
7302                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7303         }
7304
7305         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
7306         brighten = r_bloom_brighten.value;
7307         if (r_hdr.integer)
7308                 brighten *= r_hdr_range.value;
7309         brighten = sqrt(brighten);
7310         if(range >= 1)
7311                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
7312         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7313         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
7314
7315         for (dir = 0;dir < 2;dir++)
7316         {
7317                 // blend on at multiple vertical offsets to achieve a vertical blur
7318                 // TODO: do offset blends using GLSL
7319                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
7320                 GL_BlendFunc(GL_ONE, GL_ZERO);
7321                 for (x = -range;x <= range;x++)
7322                 {
7323                         if (!dir){xoffset = 0;yoffset = x;}
7324                         else {xoffset = x;yoffset = 0;}
7325                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
7326                         yoffset /= (float)r_bloomstate.bloomtextureheight;
7327                         // compute a texcoord array with the specified x and y offset
7328                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
7329                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7330                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7331                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7332                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7333                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
7334                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
7335                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
7336                         // this r value looks like a 'dot' particle, fading sharply to
7337                         // black at the edges
7338                         // (probably not realistic but looks good enough)
7339                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
7340                         //r = brighten/(range*2+1);
7341                         r = brighten / (range * 2 + 1);
7342                         if(range >= 1)
7343                                 r *= (1 - x*x/(float)(range*range));
7344                         GL_Color(r, r, r, 1);
7345                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7346                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7347                         GL_BlendFunc(GL_ONE, GL_ONE);
7348                 }
7349
7350                 // copy the vertically blurred bloom view to a texture
7351                 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);
7352                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7353         }
7354
7355         // apply subtract last
7356         // (just like it would be in a GLSL shader)
7357         if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
7358         {
7359                 GL_BlendFunc(GL_ONE, GL_ZERO);
7360                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7361                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7362                 GL_Color(1, 1, 1, 1);
7363                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7364                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7365
7366                 GL_BlendFunc(GL_ONE, GL_ONE);
7367                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
7368                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7369                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7370                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
7371                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7372                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7373                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
7374
7375                 // copy the darkened bloom view to a texture
7376                 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);
7377                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7378         }
7379 }
7380
7381 void R_HDR_RenderBloomTexture(void)
7382 {
7383         int oldwidth, oldheight;
7384         float oldcolorscale;
7385
7386         oldcolorscale = r_refdef.view.colorscale;
7387         oldwidth = r_refdef.view.width;
7388         oldheight = r_refdef.view.height;
7389         r_refdef.view.width = r_bloomstate.bloomwidth;
7390         r_refdef.view.height = r_bloomstate.bloomheight;
7391
7392         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
7393         // TODO: add exposure compensation features
7394         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
7395
7396         r_refdef.view.showdebug = false;
7397         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
7398
7399         R_ResetViewRendering3D();
7400
7401         R_ClearScreen(r_refdef.fogenabled);
7402         if (r_timereport_active)
7403                 R_TimeReport("HDRclear");
7404
7405         R_View_Update();
7406         if (r_timereport_active)
7407                 R_TimeReport("visibility");
7408
7409         // only do secondary renders with HDR if r_hdr is 2 or higher
7410         r_waterstate.numwaterplanes = 0;
7411         if (r_waterstate.enabled && r_hdr.integer >= 2)
7412                 R_RenderWaterPlanes();
7413
7414         r_refdef.view.showdebug = true;
7415         R_RenderScene();
7416         r_waterstate.numwaterplanes = 0;
7417
7418         R_ResetViewRendering2D();
7419
7420         R_Bloom_CopyHDRTexture();
7421         R_Bloom_MakeTexture();
7422
7423         // restore the view settings
7424         r_refdef.view.width = oldwidth;
7425         r_refdef.view.height = oldheight;
7426         r_refdef.view.colorscale = oldcolorscale;
7427
7428         R_ResetViewRendering3D();
7429
7430         R_ClearScreen(r_refdef.fogenabled);
7431         if (r_timereport_active)
7432                 R_TimeReport("viewclear");
7433 }
7434
7435 static void R_BlendView(void)
7436 {
7437         unsigned int permutation;
7438         float uservecs[4][4];
7439
7440         switch (vid.renderpath)
7441         {
7442         case RENDERPATH_GL20:
7443         case RENDERPATH_CGGL:
7444                 permutation =
7445                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
7446                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
7447                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
7448                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
7449                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
7450
7451                 if (r_bloomstate.texture_screen)
7452                 {
7453                         // make sure the buffer is available
7454                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
7455
7456                         R_ResetViewRendering2D();
7457                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7458                         R_Mesh_ColorPointer(NULL, 0, 0);
7459
7460                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
7461                         {
7462                                 // declare variables
7463                                 float speed;
7464                                 static float avgspeed;
7465
7466                                 speed = VectorLength(cl.movement_velocity);
7467
7468                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
7469                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
7470
7471                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
7472                                 speed = bound(0, speed, 1);
7473                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
7474
7475                                 // calculate values into a standard alpha
7476                                 cl.motionbluralpha = 1 - exp(-
7477                                                 (
7478                                                  (r_motionblur.value * speed / 80)
7479                                                  +
7480                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
7481                                                 )
7482                                                 /
7483                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
7484                                            );
7485
7486                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
7487                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
7488                                 // apply the blur
7489                                 if (cl.motionbluralpha > 0)
7490                                 {
7491                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7492                                         GL_Color(1, 1, 1, cl.motionbluralpha);
7493                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7494                                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7495                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7496                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7497                                 }
7498                         }
7499
7500                         // copy view into the screen texture
7501                         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);
7502                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7503                 }
7504                 else if (!r_bloomstate.texture_bloom)
7505                 {
7506                         // we may still have to do view tint...
7507                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7508                         {
7509                                 // apply a color tint to the whole view
7510                                 R_ResetViewRendering2D();
7511                                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7512                                 R_Mesh_ColorPointer(NULL, 0, 0);
7513                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7514                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7515                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7516                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7517                         }
7518                         break; // no screen processing, no bloom, skip it
7519                 }
7520
7521                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
7522                 {
7523                         // render simple bloom effect
7524                         // copy the screen and shrink it and darken it for the bloom process
7525                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
7526                         // make the bloom texture
7527                         R_Bloom_MakeTexture();
7528                 }
7529
7530 #if _MSC_VER >= 1400
7531 #define sscanf sscanf_s
7532 #endif
7533                 memset(uservecs, 0, sizeof(uservecs));
7534                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
7535                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
7536                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
7537                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
7538
7539                 R_ResetViewRendering2D();
7540                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7541                 R_Mesh_ColorPointer(NULL, 0, 0);
7542                 GL_Color(1, 1, 1, 1);
7543                 GL_BlendFunc(GL_ONE, GL_ZERO);
7544                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7545                 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7546
7547                 switch(vid.renderpath)
7548                 {
7549                 case RENDERPATH_GL20:
7550                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
7551                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
7552                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
7553                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
7554                         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]);
7555                         if (r_glsl_permutation->loc_ClientTime         >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime        , cl.time);
7556                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
7557                         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]);
7558                         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]);
7559                         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]);
7560                         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]);
7561                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
7562                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
7563                         break;
7564                 case RENDERPATH_CGGL:
7565 #ifdef SUPPORTCG
7566                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
7567                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
7568                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
7569                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
7570                         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
7571                         if (r_cg_permutation->fp_ClientTime        ) cgGLSetParameter1f(     r_cg_permutation->fp_ClientTime        , cl.time);CHECKCGERROR
7572                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
7573                         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
7574                         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
7575                         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
7576                         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
7577                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
7578                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
7579 #endif
7580                         break;
7581                 default:
7582                         break;
7583                 }
7584                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7585                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7586                 break;
7587         case RENDERPATH_GL13:
7588         case RENDERPATH_GL11:
7589                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7590                 {
7591                         // apply a color tint to the whole view
7592                         R_ResetViewRendering2D();
7593                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7594                         R_Mesh_ColorPointer(NULL, 0, 0);
7595                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7596                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7597                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7598                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7599                 }
7600                 break;
7601         }
7602 }
7603
7604 matrix4x4_t r_waterscrollmatrix;
7605
7606 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
7607 {
7608         if (r_refdef.fog_density)
7609         {
7610                 r_refdef.fogcolor[0] = r_refdef.fog_red;
7611                 r_refdef.fogcolor[1] = r_refdef.fog_green;
7612                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7613
7614                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7615                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7616                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7617                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7618
7619                 {
7620                         vec3_t fogvec;
7621                         VectorCopy(r_refdef.fogcolor, fogvec);
7622                         //   color.rgb *= ContrastBoost * SceneBrightness;
7623                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7624                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7625                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7626                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7627                 }
7628         }
7629 }
7630
7631 void R_UpdateVariables(void)
7632 {
7633         R_Textures_Frame();
7634
7635         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7636
7637         r_refdef.farclip = r_farclip_base.value;
7638         if (r_refdef.scene.worldmodel)
7639                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7640         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7641
7642         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7643                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7644         r_refdef.polygonfactor = 0;
7645         r_refdef.polygonoffset = 0;
7646         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7647         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7648
7649         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7650         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7651         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
7652         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7653         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7654         if (r_showsurfaces.integer)
7655         {
7656                 r_refdef.scene.rtworld = false;
7657                 r_refdef.scene.rtworldshadows = false;
7658                 r_refdef.scene.rtdlight = false;
7659                 r_refdef.scene.rtdlightshadows = false;
7660                 r_refdef.lightmapintensity = 0;
7661         }
7662
7663         if (gamemode == GAME_NEHAHRA)
7664         {
7665                 if (gl_fogenable.integer)
7666                 {
7667                         r_refdef.oldgl_fogenable = true;
7668                         r_refdef.fog_density = gl_fogdensity.value;
7669                         r_refdef.fog_red = gl_fogred.value;
7670                         r_refdef.fog_green = gl_foggreen.value;
7671                         r_refdef.fog_blue = gl_fogblue.value;
7672                         r_refdef.fog_alpha = 1;
7673                         r_refdef.fog_start = 0;
7674                         r_refdef.fog_end = gl_skyclip.value;
7675                         r_refdef.fog_height = 1<<30;
7676                         r_refdef.fog_fadedepth = 128;
7677                 }
7678                 else if (r_refdef.oldgl_fogenable)
7679                 {
7680                         r_refdef.oldgl_fogenable = false;
7681                         r_refdef.fog_density = 0;
7682                         r_refdef.fog_red = 0;
7683                         r_refdef.fog_green = 0;
7684                         r_refdef.fog_blue = 0;
7685                         r_refdef.fog_alpha = 0;
7686                         r_refdef.fog_start = 0;
7687                         r_refdef.fog_end = 0;
7688                         r_refdef.fog_height = 1<<30;
7689                         r_refdef.fog_fadedepth = 128;
7690                 }
7691         }
7692
7693         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7694         r_refdef.fog_start = max(0, r_refdef.fog_start);
7695         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7696
7697         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
7698
7699         if (r_refdef.fog_density && r_drawfog.integer)
7700         {
7701                 r_refdef.fogenabled = true;
7702                 // this is the point where the fog reaches 0.9986 alpha, which we
7703                 // consider a good enough cutoff point for the texture
7704                 // (0.9986 * 256 == 255.6)
7705                 if (r_fog_exp2.integer)
7706                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7707                 else
7708                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7709                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7710                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7711                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7712                 // fog color was already set
7713                 // update the fog texture
7714                 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)
7715                         R_BuildFogTexture();
7716         }
7717         else
7718                 r_refdef.fogenabled = false;
7719
7720         switch(vid.renderpath)
7721         {
7722         case RENDERPATH_GL20:
7723         case RENDERPATH_CGGL:
7724                 if(v_glslgamma.integer && !vid_gammatables_trivial)
7725                 {
7726                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7727                         {
7728                                 // build GLSL gamma texture
7729 #define RAMPWIDTH 256
7730                                 unsigned short ramp[RAMPWIDTH * 3];
7731                                 unsigned char rampbgr[RAMPWIDTH][4];
7732                                 int i;
7733
7734                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7735
7736                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7737                                 for(i = 0; i < RAMPWIDTH; ++i)
7738                                 {
7739                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7740                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7741                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7742                                         rampbgr[i][3] = 0;
7743                                 }
7744                                 if (r_texture_gammaramps)
7745                                 {
7746                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
7747                                 }
7748                                 else
7749                                 {
7750                                         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);
7751                                 }
7752                         }
7753                 }
7754                 else
7755                 {
7756                         // remove GLSL gamma texture
7757                 }
7758                 break;
7759         case RENDERPATH_GL13:
7760         case RENDERPATH_GL11:
7761                 break;
7762         }
7763 }
7764
7765 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7766 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7767 /*
7768 ================
7769 R_SelectScene
7770 ================
7771 */
7772 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7773         if( scenetype != r_currentscenetype ) {
7774                 // store the old scenetype
7775                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7776                 r_currentscenetype = scenetype;
7777                 // move in the new scene
7778                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7779         }
7780 }
7781
7782 /*
7783 ================
7784 R_GetScenePointer
7785 ================
7786 */
7787 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7788 {
7789         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7790         if( scenetype == r_currentscenetype ) {
7791                 return &r_refdef.scene;
7792         } else {
7793                 return &r_scenes_store[ scenetype ];
7794         }
7795 }
7796
7797 /*
7798 ================
7799 R_RenderView
7800 ================
7801 */
7802 void R_RenderView(void)
7803 {
7804         if (r_timereport_active)
7805                 R_TimeReport("start");
7806         r_textureframe++; // used only by R_GetCurrentTexture
7807         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7808
7809         if (!r_drawentities.integer)
7810                 r_refdef.scene.numentities = 0;
7811
7812         R_AnimCache_ClearCache();
7813         R_FrameData_NewFrame();
7814
7815         if (r_refdef.view.isoverlay)
7816         {
7817                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7818                 GL_Clear( GL_DEPTH_BUFFER_BIT );
7819                 R_TimeReport("depthclear");
7820
7821                 r_refdef.view.showdebug = false;
7822
7823                 r_waterstate.enabled = false;
7824                 r_waterstate.numwaterplanes = 0;
7825
7826                 R_RenderScene();
7827
7828                 CHECKGLERROR
7829                 return;
7830         }
7831
7832         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
7833                 return; //Host_Error ("R_RenderView: NULL worldmodel");
7834
7835         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
7836
7837         // break apart the view matrix into vectors for various purposes
7838         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
7839         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
7840         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
7841         VectorNegate(r_refdef.view.left, r_refdef.view.right);
7842         // make an inverted copy of the view matrix for tracking sprites
7843         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
7844
7845         R_Shadow_UpdateWorldLightSelection();
7846
7847         R_Bloom_StartFrame();
7848         R_Water_StartFrame();
7849
7850         CHECKGLERROR
7851         if (r_timereport_active)
7852                 R_TimeReport("viewsetup");
7853
7854         R_ResetViewRendering3D();
7855
7856         if (r_refdef.view.clear || r_refdef.fogenabled)
7857         {
7858                 R_ClearScreen(r_refdef.fogenabled);
7859                 if (r_timereport_active)
7860                         R_TimeReport("viewclear");
7861         }
7862         r_refdef.view.clear = true;
7863
7864         // this produces a bloom texture to be used in R_BlendView() later
7865         if (r_hdr.integer && r_bloomstate.bloomwidth)
7866         {
7867                 R_HDR_RenderBloomTexture();
7868                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
7869                 r_textureframe++; // used only by R_GetCurrentTexture
7870         }
7871
7872         r_refdef.view.showdebug = true;
7873
7874         R_View_Update();
7875         if (r_timereport_active)
7876                 R_TimeReport("visibility");
7877
7878         r_waterstate.numwaterplanes = 0;
7879         if (r_waterstate.enabled)
7880                 R_RenderWaterPlanes();
7881
7882         R_RenderScene();
7883         r_waterstate.numwaterplanes = 0;
7884
7885         R_BlendView();
7886         if (r_timereport_active)
7887                 R_TimeReport("blendview");
7888
7889         GL_Scissor(0, 0, vid.width, vid.height);
7890         GL_ScissorTest(false);
7891         CHECKGLERROR
7892 }
7893
7894 void R_RenderWaterPlanes(void)
7895 {
7896         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7897         {
7898                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7899                 if (r_timereport_active)
7900                         R_TimeReport("waterworld");
7901         }
7902
7903         // don't let sound skip if going slow
7904         if (r_refdef.scene.extraupdate)
7905                 S_ExtraUpdate ();
7906
7907         R_DrawModelsAddWaterPlanes();
7908         if (r_timereport_active)
7909                 R_TimeReport("watermodels");
7910
7911         if (r_waterstate.numwaterplanes)
7912         {
7913                 R_Water_ProcessPlanes();
7914                 if (r_timereport_active)
7915                         R_TimeReport("waterscenes");
7916         }
7917 }
7918
7919 extern void R_DrawLightningBeams (void);
7920 extern void VM_CL_AddPolygonsToMeshQueue (void);
7921 extern void R_DrawPortals (void);
7922 extern cvar_t cl_locs_show;
7923 static void R_DrawLocs(void);
7924 static void R_DrawEntityBBoxes(void);
7925 static void R_DrawModelDecals(void);
7926 extern cvar_t cl_decals_newsystem;
7927 extern qboolean r_shadow_usingdeferredprepass;
7928 void R_RenderScene(void)
7929 {
7930         r_refdef.stats.renders++;
7931
7932         R_UpdateFogColor();
7933
7934         // don't let sound skip if going slow
7935         if (r_refdef.scene.extraupdate)
7936                 S_ExtraUpdate ();
7937
7938         R_MeshQueue_BeginScene();
7939
7940         R_SkyStartFrame();
7941
7942         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);
7943
7944         if (cl.csqc_vidvars.drawworld)
7945         {
7946                 // don't let sound skip if going slow
7947                 if (r_refdef.scene.extraupdate)
7948                         S_ExtraUpdate ();
7949
7950                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7951                 {
7952                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7953                         if (r_timereport_active)
7954                                 R_TimeReport("worldsky");
7955                 }
7956
7957                 if (R_DrawBrushModelsSky() && r_timereport_active)
7958                         R_TimeReport("bmodelsky");
7959
7960                 if (skyrendermasked && skyrenderlater)
7961                 {
7962                         // we have to force off the water clipping plane while rendering sky
7963                         R_SetupView(false);
7964                         R_Sky();
7965                         R_SetupView(true);
7966                         if (r_timereport_active)
7967                                 R_TimeReport("sky");
7968                 }
7969         }
7970
7971         R_AnimCache_CacheVisibleEntities();
7972         if (r_timereport_active)
7973                 R_TimeReport("animation");
7974
7975         R_Shadow_PrepareLights();
7976         if (r_timereport_active)
7977                 R_TimeReport("preparelights");
7978
7979         if (r_shadow_usingdeferredprepass)
7980                 R_Shadow_DrawPrepass();
7981
7982         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7983         {
7984                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7985                 if (r_timereport_active)
7986                         R_TimeReport("worlddepth");
7987         }
7988         if (r_depthfirst.integer >= 2)
7989         {
7990                 R_DrawModelsDepth();
7991                 if (r_timereport_active)
7992                         R_TimeReport("modeldepth");
7993         }
7994
7995         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7996         {
7997                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7998                 if (r_timereport_active)
7999                         R_TimeReport("world");
8000         }
8001
8002         // don't let sound skip if going slow
8003         if (r_refdef.scene.extraupdate)
8004                 S_ExtraUpdate ();
8005
8006         R_DrawModels();
8007         if (r_timereport_active)
8008                 R_TimeReport("models");
8009
8010         // don't let sound skip if going slow
8011         if (r_refdef.scene.extraupdate)
8012                 S_ExtraUpdate ();
8013
8014         if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8015         {
8016                 R_DrawModelShadows();
8017                 R_ResetViewRendering3D();
8018                 // don't let sound skip if going slow
8019                 if (r_refdef.scene.extraupdate)
8020                         S_ExtraUpdate ();
8021         }
8022
8023         if (!r_shadow_usingdeferredprepass)
8024         {
8025                 R_Shadow_DrawLights();
8026                 if (r_timereport_active)
8027                         R_TimeReport("rtlights");
8028         }
8029
8030         // don't let sound skip if going slow
8031         if (r_refdef.scene.extraupdate)
8032                 S_ExtraUpdate ();
8033
8034         if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8035         {
8036                 R_DrawModelShadows();
8037                 R_ResetViewRendering3D();
8038                 // don't let sound skip if going slow
8039                 if (r_refdef.scene.extraupdate)
8040                         S_ExtraUpdate ();
8041         }
8042
8043         if (cl.csqc_vidvars.drawworld)
8044         {
8045                 if (cl_decals_newsystem.integer)
8046                 {
8047                         R_DrawModelDecals();
8048                         if (r_timereport_active)
8049                                 R_TimeReport("modeldecals");
8050                 }
8051                 else
8052                 {
8053                         R_DrawDecals();
8054                         if (r_timereport_active)
8055                                 R_TimeReport("decals");
8056                 }
8057
8058                 R_DrawParticles();
8059                 if (r_timereport_active)
8060                         R_TimeReport("particles");
8061
8062                 R_DrawExplosions();
8063                 if (r_timereport_active)
8064                         R_TimeReport("explosions");
8065
8066                 R_DrawLightningBeams();
8067                 if (r_timereport_active)
8068                         R_TimeReport("lightning");
8069         }
8070
8071         VM_CL_AddPolygonsToMeshQueue();
8072
8073         if (r_refdef.view.showdebug)
8074         {
8075                 if (cl_locs_show.integer)
8076                 {
8077                         R_DrawLocs();
8078                         if (r_timereport_active)
8079                                 R_TimeReport("showlocs");
8080                 }
8081
8082                 if (r_drawportals.integer)
8083                 {
8084                         R_DrawPortals();
8085                         if (r_timereport_active)
8086                                 R_TimeReport("portals");
8087                 }
8088
8089                 if (r_showbboxes.value > 0)
8090                 {
8091                         R_DrawEntityBBoxes();
8092                         if (r_timereport_active)
8093                                 R_TimeReport("bboxes");
8094                 }
8095         }
8096
8097         R_MeshQueue_RenderTransparent();
8098         if (r_timereport_active)
8099                 R_TimeReport("drawtrans");
8100
8101         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))
8102         {
8103                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
8104                 if (r_timereport_active)
8105                         R_TimeReport("worlddebug");
8106                 R_DrawModelsDebug();
8107                 if (r_timereport_active)
8108                         R_TimeReport("modeldebug");
8109         }
8110
8111         if (cl.csqc_vidvars.drawworld)
8112         {
8113                 R_Shadow_DrawCoronas();
8114                 if (r_timereport_active)
8115                         R_TimeReport("coronas");
8116         }
8117
8118         // don't let sound skip if going slow
8119         if (r_refdef.scene.extraupdate)
8120                 S_ExtraUpdate ();
8121
8122         R_ResetViewRendering2D();
8123 }
8124
8125 static const unsigned short bboxelements[36] =
8126 {
8127         5, 1, 3, 5, 3, 7,
8128         6, 2, 0, 6, 0, 4,
8129         7, 3, 2, 7, 2, 6,
8130         4, 0, 1, 4, 1, 5,
8131         4, 5, 7, 4, 7, 6,
8132         1, 0, 2, 1, 2, 3,
8133 };
8134
8135 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
8136 {
8137         int i;
8138         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
8139
8140         RSurf_ActiveWorldEntity();
8141
8142         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8143         GL_DepthMask(false);
8144         GL_DepthRange(0, 1);
8145         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8146         R_Mesh_ResetTextureState();
8147
8148         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
8149         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
8150         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
8151         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
8152         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
8153         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
8154         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
8155         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
8156         R_FillColors(color4f, 8, cr, cg, cb, ca);
8157         if (r_refdef.fogenabled)
8158         {
8159                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
8160                 {
8161                         f1 = RSurf_FogVertex(v);
8162                         f2 = 1 - f1;
8163                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
8164                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
8165                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
8166                 }
8167         }
8168         R_Mesh_VertexPointer(vertex3f, 0, 0);
8169         R_Mesh_ColorPointer(color4f, 0, 0);
8170         R_Mesh_ResetTextureState();
8171         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8172         R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
8173 }
8174
8175 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8176 {
8177         int i;
8178         float color[4];
8179         prvm_edict_t *edict;
8180         prvm_prog_t *prog_save = prog;
8181
8182         // this function draws bounding boxes of server entities
8183         if (!sv.active)
8184                 return;
8185
8186         GL_CullFace(GL_NONE);
8187         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8188
8189         prog = 0;
8190         SV_VM_Begin();
8191         for (i = 0;i < numsurfaces;i++)
8192         {
8193                 edict = PRVM_EDICT_NUM(surfacelist[i]);
8194                 switch ((int)edict->fields.server->solid)
8195                 {
8196                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
8197                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
8198                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
8199                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
8200                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
8201                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
8202                 }
8203                 color[3] *= r_showbboxes.value;
8204                 color[3] = bound(0, color[3], 1);
8205                 GL_DepthTest(!r_showdisabledepthtest.integer);
8206                 GL_CullFace(r_refdef.view.cullface_front);
8207                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
8208         }
8209         SV_VM_End();
8210         prog = prog_save;
8211 }
8212
8213 static void R_DrawEntityBBoxes(void)
8214 {
8215         int i;
8216         prvm_edict_t *edict;
8217         vec3_t center;
8218         prvm_prog_t *prog_save = prog;
8219
8220         // this function draws bounding boxes of server entities
8221         if (!sv.active)
8222                 return;
8223
8224         prog = 0;
8225         SV_VM_Begin();
8226         for (i = 0;i < prog->num_edicts;i++)
8227         {
8228                 edict = PRVM_EDICT_NUM(i);
8229                 if (edict->priv.server->free)
8230                         continue;
8231                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
8232                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
8233                         continue;
8234                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
8235                         continue;
8236                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
8237                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
8238         }
8239         SV_VM_End();
8240         prog = prog_save;
8241 }
8242
8243 static const int nomodelelement3i[24] =
8244 {
8245         5, 2, 0,
8246         5, 1, 2,
8247         5, 0, 3,
8248         5, 3, 1,
8249         0, 2, 4,
8250         2, 1, 4,
8251         3, 0, 4,
8252         1, 3, 4
8253 };
8254
8255 static const unsigned short nomodelelement3s[24] =
8256 {
8257         5, 2, 0,
8258         5, 1, 2,
8259         5, 0, 3,
8260         5, 3, 1,
8261         0, 2, 4,
8262         2, 1, 4,
8263         3, 0, 4,
8264         1, 3, 4
8265 };
8266
8267 static const float nomodelvertex3f[6*3] =
8268 {
8269         -16,   0,   0,
8270          16,   0,   0,
8271           0, -16,   0,
8272           0,  16,   0,
8273           0,   0, -16,
8274           0,   0,  16
8275 };
8276
8277 static const float nomodelcolor4f[6*4] =
8278 {
8279         0.0f, 0.0f, 0.5f, 1.0f,
8280         0.0f, 0.0f, 0.5f, 1.0f,
8281         0.0f, 0.5f, 0.0f, 1.0f,
8282         0.0f, 0.5f, 0.0f, 1.0f,
8283         0.5f, 0.0f, 0.0f, 1.0f,
8284         0.5f, 0.0f, 0.0f, 1.0f
8285 };
8286
8287 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8288 {
8289         int i;
8290         float f1, f2, *c;
8291         float color4f[6*4];
8292
8293         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);
8294
8295         // this is only called once per entity so numsurfaces is always 1, and
8296         // surfacelist is always {0}, so this code does not handle batches
8297
8298         if (rsurface.ent_flags & RENDER_ADDITIVE)
8299         {
8300                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
8301                 GL_DepthMask(false);
8302         }
8303         else if (rsurface.colormod[3] < 1)
8304         {
8305                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8306                 GL_DepthMask(false);
8307         }
8308         else
8309         {
8310                 GL_BlendFunc(GL_ONE, GL_ZERO);
8311                 GL_DepthMask(true);
8312         }
8313         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8314         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8315         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8316         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8317         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8318         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
8319         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8320         R_Mesh_ColorPointer(color4f, 0, 0);
8321         for (i = 0, c = color4f;i < 6;i++, c += 4)
8322         {
8323                 c[0] *= rsurface.colormod[0];
8324                 c[1] *= rsurface.colormod[1];
8325                 c[2] *= rsurface.colormod[2];
8326                 c[3] *= rsurface.colormod[3];
8327         }
8328         if (r_refdef.fogenabled)
8329         {
8330                 for (i = 0, c = color4f;i < 6;i++, c += 4)
8331                 {
8332                         f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
8333                         f2 = 1 - f1;
8334                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8335                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8336                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8337                 }
8338         }
8339         R_Mesh_ResetTextureState();
8340         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
8341 }
8342
8343 void R_DrawNoModel(entity_render_t *ent)
8344 {
8345         vec3_t org;
8346         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8347         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8348                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8349         else
8350                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8351 }
8352
8353 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8354 {
8355         vec3_t right1, right2, diff, normal;
8356
8357         VectorSubtract (org2, org1, normal);
8358
8359         // calculate 'right' vector for start
8360         VectorSubtract (r_refdef.view.origin, org1, diff);
8361         CrossProduct (normal, diff, right1);
8362         VectorNormalize (right1);
8363
8364         // calculate 'right' vector for end
8365         VectorSubtract (r_refdef.view.origin, org2, diff);
8366         CrossProduct (normal, diff, right2);
8367         VectorNormalize (right2);
8368
8369         vert[ 0] = org1[0] + width * right1[0];
8370         vert[ 1] = org1[1] + width * right1[1];
8371         vert[ 2] = org1[2] + width * right1[2];
8372         vert[ 3] = org1[0] - width * right1[0];
8373         vert[ 4] = org1[1] - width * right1[1];
8374         vert[ 5] = org1[2] - width * right1[2];
8375         vert[ 6] = org2[0] - width * right2[0];
8376         vert[ 7] = org2[1] - width * right2[1];
8377         vert[ 8] = org2[2] - width * right2[2];
8378         vert[ 9] = org2[0] + width * right2[0];
8379         vert[10] = org2[1] + width * right2[1];
8380         vert[11] = org2[2] + width * right2[2];
8381 }
8382
8383 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)
8384 {
8385         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8386         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8387         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8388         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8389         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8390         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8391         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8392         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8393         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8394         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8395         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8396         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8397 }
8398
8399 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8400 {
8401         int i;
8402         float *vertex3f;
8403         float v[3];
8404         VectorSet(v, x, y, z);
8405         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8406                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8407                         break;
8408         if (i == mesh->numvertices)
8409         {
8410                 if (mesh->numvertices < mesh->maxvertices)
8411                 {
8412                         VectorCopy(v, vertex3f);
8413                         mesh->numvertices++;
8414                 }
8415                 return mesh->numvertices;
8416         }
8417         else
8418                 return i;
8419 }
8420
8421 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8422 {
8423         int i;
8424         int *e, element[3];
8425         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8426         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8427         e = mesh->element3i + mesh->numtriangles * 3;
8428         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8429         {
8430                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8431                 if (mesh->numtriangles < mesh->maxtriangles)
8432                 {
8433                         *e++ = element[0];
8434                         *e++ = element[1];
8435                         *e++ = element[2];
8436                         mesh->numtriangles++;
8437                 }
8438                 element[1] = element[2];
8439         }
8440 }
8441
8442 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8443 {
8444         int i;
8445         int *e, element[3];
8446         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8447         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8448         e = mesh->element3i + mesh->numtriangles * 3;
8449         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8450         {
8451                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8452                 if (mesh->numtriangles < mesh->maxtriangles)
8453                 {
8454                         *e++ = element[0];
8455                         *e++ = element[1];
8456                         *e++ = element[2];
8457                         mesh->numtriangles++;
8458                 }
8459                 element[1] = element[2];
8460         }
8461 }
8462
8463 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8464 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8465 {
8466         int planenum, planenum2;
8467         int w;
8468         int tempnumpoints;
8469         mplane_t *plane, *plane2;
8470         double maxdist;
8471         double temppoints[2][256*3];
8472         // figure out how large a bounding box we need to properly compute this brush
8473         maxdist = 0;
8474         for (w = 0;w < numplanes;w++)
8475                 maxdist = max(maxdist, fabs(planes[w].dist));
8476         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8477         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8478         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8479         {
8480                 w = 0;
8481                 tempnumpoints = 4;
8482                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8483                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8484                 {
8485                         if (planenum2 == planenum)
8486                                 continue;
8487                         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);
8488                         w = !w;
8489                 }
8490                 if (tempnumpoints < 3)
8491                         continue;
8492                 // generate elements forming a triangle fan for this polygon
8493                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8494         }
8495 }
8496
8497 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)
8498 {
8499         texturelayer_t *layer;
8500         layer = t->currentlayers + t->currentnumlayers++;
8501         layer->type = type;
8502         layer->depthmask = depthmask;
8503         layer->blendfunc1 = blendfunc1;
8504         layer->blendfunc2 = blendfunc2;
8505         layer->texture = texture;
8506         layer->texmatrix = *matrix;
8507         layer->color[0] = r;
8508         layer->color[1] = g;
8509         layer->color[2] = b;
8510         layer->color[3] = a;
8511 }
8512
8513 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8514 {
8515         double index, f;
8516         index = parms[2] + r_refdef.scene.time * parms[3];
8517         index -= floor(index);
8518         switch (func)
8519         {
8520         default:
8521         case Q3WAVEFUNC_NONE:
8522         case Q3WAVEFUNC_NOISE:
8523         case Q3WAVEFUNC_COUNT:
8524                 f = 0;
8525                 break;
8526         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8527         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8528         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8529         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8530         case Q3WAVEFUNC_TRIANGLE:
8531                 index *= 4;
8532                 f = index - floor(index);
8533                 if (index < 1)
8534                         f = f;
8535                 else if (index < 2)
8536                         f = 1 - f;
8537                 else if (index < 3)
8538                         f = -f;
8539                 else
8540                         f = -(1 - f);
8541                 break;
8542         }
8543         return (float)(parms[0] + parms[1] * f);
8544 }
8545
8546 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8547 {
8548         int w, h, idx;
8549         float f;
8550         float tcmat[12];
8551         matrix4x4_t matrix, temp;
8552         switch(tcmod->tcmod)
8553         {
8554                 case Q3TCMOD_COUNT:
8555                 case Q3TCMOD_NONE:
8556                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8557                                 matrix = r_waterscrollmatrix;
8558                         else
8559                                 matrix = identitymatrix;
8560                         break;
8561                 case Q3TCMOD_ENTITYTRANSLATE:
8562                         // this is used in Q3 to allow the gamecode to control texcoord
8563                         // scrolling on the entity, which is not supported in darkplaces yet.
8564                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8565                         break;
8566                 case Q3TCMOD_ROTATE:
8567                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8568                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
8569                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8570                         break;
8571                 case Q3TCMOD_SCALE:
8572                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8573                         break;
8574                 case Q3TCMOD_SCROLL:
8575                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
8576                         break;
8577                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8578                         w = (int) tcmod->parms[0];
8579                         h = (int) tcmod->parms[1];
8580                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
8581                         f = f - floor(f);
8582                         idx = (int) floor(f * w * h);
8583                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8584                         break;
8585                 case Q3TCMOD_STRETCH:
8586                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8587                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8588                         break;
8589                 case Q3TCMOD_TRANSFORM:
8590                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8591                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8592                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8593                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8594                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8595                         break;
8596                 case Q3TCMOD_TURBULENT:
8597                         // this is handled in the RSurf_PrepareVertices function
8598                         matrix = identitymatrix;
8599                         break;
8600         }
8601         temp = *texmatrix;
8602         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8603 }
8604
8605 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8606 {
8607         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
8608         char name[MAX_QPATH];
8609         skinframe_t *skinframe;
8610         unsigned char pixels[296*194];
8611         strlcpy(cache->name, skinname, sizeof(cache->name));
8612         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8613         if (developer_loading.integer)
8614                 Con_Printf("loading %s\n", name);
8615         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8616         if (!skinframe || !skinframe->base)
8617         {
8618                 unsigned char *f;
8619                 fs_offset_t filesize;
8620                 skinframe = NULL;
8621                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8622                 if (f)
8623                 {
8624                         if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
8625                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8626                         Mem_Free(f);
8627                 }
8628         }
8629         cache->skinframe = skinframe;
8630 }
8631
8632 texture_t *R_GetCurrentTexture(texture_t *t)
8633 {
8634         int i;
8635         const entity_render_t *ent = rsurface.entity;
8636         dp_model_t *model = ent->model;
8637         q3shaderinfo_layer_tcmod_t *tcmod;
8638
8639         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
8640                 return t->currentframe;
8641         t->update_lastrenderframe = r_textureframe;
8642         t->update_lastrenderentity = (void *)ent;
8643
8644         // switch to an alternate material if this is a q1bsp animated material
8645         {
8646                 texture_t *texture = t;
8647                 int s = rsurface.ent_skinnum;
8648                 if ((unsigned int)s >= (unsigned int)model->numskins)
8649                         s = 0;
8650                 if (model->skinscenes)
8651                 {
8652                         if (model->skinscenes[s].framecount > 1)
8653                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8654                         else
8655                                 s = model->skinscenes[s].firstframe;
8656                 }
8657                 if (s > 0)
8658                         t = t + s * model->num_surfaces;
8659                 if (t->animated)
8660                 {
8661                         // use an alternate animation if the entity's frame is not 0,
8662                         // and only if the texture has an alternate animation
8663                         if (rsurface.ent_alttextures && t->anim_total[1])
8664                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
8665                         else
8666                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
8667                 }
8668                 texture->currentframe = t;
8669         }
8670
8671         // update currentskinframe to be a qw skin or animation frame
8672         if (rsurface.ent_qwskin >= 0)
8673         {
8674                 i = rsurface.ent_qwskin;
8675                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8676                 {
8677                         r_qwskincache_size = cl.maxclients;
8678                         if (r_qwskincache)
8679                                 Mem_Free(r_qwskincache);
8680                         r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8681                 }
8682                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8683                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8684                 t->currentskinframe = r_qwskincache[i].skinframe;
8685                 if (t->currentskinframe == NULL)
8686                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8687         }
8688         else if (t->numskinframes >= 2)
8689                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8690         if (t->backgroundnumskinframes >= 2)
8691                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
8692
8693         t->currentmaterialflags = t->basematerialflags;
8694         t->currentalpha = rsurface.colormod[3];
8695         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
8696                 t->currentalpha *= r_wateralpha.value;
8697         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
8698                 t->currentalpha *= t->r_water_wateralpha;
8699         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
8700                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
8701         if (!(rsurface.ent_flags & RENDER_LIGHT))
8702                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8703         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8704         {
8705                 // pick a model lighting mode
8706                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8707                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8708                 else
8709                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8710         }
8711         if (rsurface.ent_flags & RENDER_ADDITIVE)
8712                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8713         else if (t->currentalpha < 1)
8714                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8715         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8716                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8717         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8718                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8719         if (t->backgroundnumskinframes)
8720                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8721         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8722         {
8723                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
8724                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8725         }
8726         else
8727                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
8728         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8729                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8730
8731         // there is no tcmod
8732         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8733         {
8734                 t->currenttexmatrix = r_waterscrollmatrix;
8735                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8736         }
8737         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8738         {
8739                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8740                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8741         }
8742
8743         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8744                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8745         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8746                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8747
8748         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8749         if (t->currentskinframe->qpixels)
8750                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8751         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8752         if (!t->basetexture)
8753                 t->basetexture = r_texture_notexture;
8754         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8755         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8756         t->nmaptexture = t->currentskinframe->nmap;
8757         if (!t->nmaptexture)
8758                 t->nmaptexture = r_texture_blanknormalmap;
8759         t->glosstexture = r_texture_black;
8760         t->glowtexture = t->currentskinframe->glow;
8761         t->fogtexture = t->currentskinframe->fog;
8762         if (t->backgroundnumskinframes)
8763         {
8764                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8765                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8766                 t->backgroundglosstexture = r_texture_black;
8767                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8768                 if (!t->backgroundnmaptexture)
8769                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8770         }
8771         else
8772         {
8773                 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
8774                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8775                 t->backgroundglosstexture = r_texture_black;
8776                 t->backgroundglowtexture = NULL;
8777         }
8778         t->specularpower = r_shadow_glossexponent.value;
8779         // TODO: store reference values for these in the texture?
8780         t->specularscale = 0;
8781         if (r_shadow_gloss.integer > 0)
8782         {
8783                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8784                 {
8785                         if (r_shadow_glossintensity.value > 0)
8786                         {
8787                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8788                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8789                                 t->specularscale = r_shadow_glossintensity.value;
8790                         }
8791                 }
8792                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8793                 {
8794                         t->glosstexture = r_texture_white;
8795                         t->backgroundglosstexture = r_texture_white;
8796                         t->specularscale = r_shadow_gloss2intensity.value;
8797                         t->specularpower = r_shadow_gloss2exponent.value;
8798                 }
8799         }
8800         t->specularscale *= t->specularscalemod;
8801         t->specularpower *= t->specularpowermod;
8802
8803         // lightmaps mode looks bad with dlights using actual texturing, so turn
8804         // off the colormap and glossmap, but leave the normalmap on as it still
8805         // accurately represents the shading involved
8806         if (gl_lightmaps.integer)
8807         {
8808                 t->basetexture = r_texture_grey128;
8809                 t->pantstexture = r_texture_black;
8810                 t->shirttexture = r_texture_black;
8811                 t->nmaptexture = r_texture_blanknormalmap;
8812                 t->glosstexture = r_texture_black;
8813                 t->glowtexture = NULL;
8814                 t->fogtexture = NULL;
8815                 t->backgroundbasetexture = NULL;
8816                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8817                 t->backgroundglosstexture = r_texture_black;
8818                 t->backgroundglowtexture = NULL;
8819                 t->specularscale = 0;
8820                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8821         }
8822
8823         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8824         VectorClear(t->dlightcolor);
8825         t->currentnumlayers = 0;
8826         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8827         {
8828                 int blendfunc1, blendfunc2;
8829                 qboolean depthmask;
8830                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8831                 {
8832                         blendfunc1 = GL_SRC_ALPHA;
8833                         blendfunc2 = GL_ONE;
8834                 }
8835                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8836                 {
8837                         blendfunc1 = GL_SRC_ALPHA;
8838                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8839                 }
8840                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8841                 {
8842                         blendfunc1 = t->customblendfunc[0];
8843                         blendfunc2 = t->customblendfunc[1];
8844                 }
8845                 else
8846                 {
8847                         blendfunc1 = GL_ONE;
8848                         blendfunc2 = GL_ZERO;
8849                 }
8850                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8851                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8852                 {
8853                         // fullbright is not affected by r_refdef.lightmapintensity
8854                         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]);
8855                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8856                                 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]);
8857                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8858                                 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]);
8859                 }
8860                 else
8861                 {
8862                         vec3_t ambientcolor;
8863                         float colorscale;
8864                         // set the color tint used for lights affecting this surface
8865                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8866                         colorscale = 2;
8867                         // q3bsp has no lightmap updates, so the lightstylevalue that
8868                         // would normally be baked into the lightmap must be
8869                         // applied to the color
8870                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8871                         if (model->type == mod_brushq3)
8872                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8873                         colorscale *= r_refdef.lightmapintensity;
8874                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8875                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8876                         // basic lit geometry
8877                         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]);
8878                         // add pants/shirt if needed
8879                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8880                                 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]);
8881                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8882                                 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]);
8883                         // now add ambient passes if needed
8884                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8885                         {
8886                                 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]);
8887                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8888                                         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]);
8889                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8890                                         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]);
8891                         }
8892                 }
8893                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8894                         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]);
8895                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8896                 {
8897                         // if this is opaque use alpha blend which will darken the earlier
8898                         // passes cheaply.
8899                         //
8900                         // if this is an alpha blended material, all the earlier passes
8901                         // were darkened by fog already, so we only need to add the fog
8902                         // color ontop through the fog mask texture
8903                         //
8904                         // if this is an additive blended material, all the earlier passes
8905                         // were darkened by fog already, and we should not add fog color
8906                         // (because the background was not darkened, there is no fog color
8907                         // that was lost behind it).
8908                         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]);
8909                 }
8910         }
8911
8912         return t->currentframe;
8913 }
8914
8915 rsurfacestate_t rsurface;
8916
8917 void R_Mesh_ResizeArrays(int newvertices)
8918 {
8919         float *base;
8920         if (rsurface.array_size >= newvertices)
8921                 return;
8922         if (rsurface.array_modelvertex3f)
8923                 Mem_Free(rsurface.array_modelvertex3f);
8924         rsurface.array_size = (newvertices + 1023) & ~1023;
8925         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
8926         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
8927         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
8928         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
8929         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
8930         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
8931         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
8932         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
8933         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
8934         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
8935         rsurface.array_color4f           = base + rsurface.array_size * 27;
8936         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
8937 }
8938
8939 void RSurf_ActiveWorldEntity(void)
8940 {
8941         dp_model_t *model = r_refdef.scene.worldmodel;
8942         //if (rsurface.entity == r_refdef.scene.worldentity)
8943         //      return;
8944         rsurface.entity = r_refdef.scene.worldentity;
8945         rsurface.skeleton = NULL;
8946         rsurface.ent_skinnum = 0;
8947         rsurface.ent_qwskin = -1;
8948         rsurface.ent_shadertime = 0;
8949         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8950         if (rsurface.array_size < model->surfmesh.num_vertices)
8951                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
8952         rsurface.matrix = identitymatrix;
8953         rsurface.inversematrix = identitymatrix;
8954         rsurface.matrixscale = 1;
8955         rsurface.inversematrixscale = 1;
8956         R_EntityMatrix(&identitymatrix);
8957         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8958         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8959         rsurface.fograngerecip = r_refdef.fograngerecip;
8960         rsurface.fogheightfade = r_refdef.fogheightfade;
8961         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8962         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8963         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8964         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8965         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8966         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8967         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8968         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8969         rsurface.colormod[3] = 1;
8970         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);
8971         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8972         rsurface.frameblend[0].lerp = 1;
8973         rsurface.ent_alttextures = false;
8974         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8975         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8976         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8977         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
8978         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8979         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8980         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
8981         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8982         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8983         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
8984         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8985         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8986         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
8987         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8988         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8989         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
8990         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8991         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8992         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
8993         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8994         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8995         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
8996         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8997         rsurface.modelelement3i = model->surfmesh.data_element3i;
8998         rsurface.modelelement3s = model->surfmesh.data_element3s;
8999         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9000         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9001         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9002         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9003         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9004         rsurface.modelsurfaces = model->data_surfaces;
9005         rsurface.generatedvertex = false;
9006         rsurface.vertex3f  = rsurface.modelvertex3f;
9007         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9008         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9009         rsurface.svector3f = rsurface.modelsvector3f;
9010         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9011         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9012         rsurface.tvector3f = rsurface.modeltvector3f;
9013         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9014         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9015         rsurface.normal3f  = rsurface.modelnormal3f;
9016         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9017         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9018         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9019 }
9020
9021 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
9022 {
9023         dp_model_t *model = ent->model;
9024         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
9025         //      return;
9026         rsurface.entity = (entity_render_t *)ent;
9027         rsurface.skeleton = ent->skeleton;
9028         rsurface.ent_skinnum = ent->skinnum;
9029         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;
9030         rsurface.ent_shadertime = ent->shadertime;
9031         rsurface.ent_flags = ent->flags;
9032         if (rsurface.array_size < model->surfmesh.num_vertices)
9033                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9034         rsurface.matrix = ent->matrix;
9035         rsurface.inversematrix = ent->inversematrix;
9036         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9037         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9038         R_EntityMatrix(&rsurface.matrix);
9039         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9040         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9041         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9042         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9043         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9044         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9045         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
9046         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
9047         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
9048         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
9049         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
9050         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
9051         rsurface.colormod[3] = ent->alpha;
9052         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
9053         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
9054         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
9055         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9056         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9057         if (ent->model->brush.submodel && !prepass)
9058         {
9059                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
9060                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
9061         }
9062         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
9063         {
9064                 if (ent->animcache_vertex3f && !r_framedata_failed)
9065                 {
9066                         rsurface.modelvertex3f = ent->animcache_vertex3f;
9067                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
9068                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
9069                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
9070                 }
9071                 else if (wanttangents)
9072                 {
9073                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9074                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9075                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9076                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9077                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
9078                 }
9079                 else if (wantnormals)
9080                 {
9081                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9082                         rsurface.modelsvector3f = NULL;
9083                         rsurface.modeltvector3f = NULL;
9084                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9085                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
9086                 }
9087                 else
9088                 {
9089                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9090                         rsurface.modelsvector3f = NULL;
9091                         rsurface.modeltvector3f = NULL;
9092                         rsurface.modelnormal3f = NULL;
9093                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
9094                 }
9095                 rsurface.modelvertex3f_bufferobject = 0;
9096                 rsurface.modelvertex3f_bufferoffset = 0;
9097                 rsurface.modelsvector3f_bufferobject = 0;
9098                 rsurface.modelsvector3f_bufferoffset = 0;
9099                 rsurface.modeltvector3f_bufferobject = 0;
9100                 rsurface.modeltvector3f_bufferoffset = 0;
9101                 rsurface.modelnormal3f_bufferobject = 0;
9102                 rsurface.modelnormal3f_bufferoffset = 0;
9103                 rsurface.generatedvertex = true;
9104         }
9105         else
9106         {
9107                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
9108                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9109                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9110                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9111                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9112                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9113                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9114                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9115                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9116                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
9117                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9118                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9119                 rsurface.generatedvertex = false;
9120         }
9121         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
9122         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9123         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9124         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
9125         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9126         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9127         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
9128         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9129         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9130         rsurface.modelelement3i = model->surfmesh.data_element3i;
9131         rsurface.modelelement3s = model->surfmesh.data_element3s;
9132         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9133         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9134         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9135         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9136         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9137         rsurface.modelsurfaces = model->data_surfaces;
9138         rsurface.vertex3f  = rsurface.modelvertex3f;
9139         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9140         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9141         rsurface.svector3f = rsurface.modelsvector3f;
9142         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9143         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9144         rsurface.tvector3f = rsurface.modeltvector3f;
9145         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9146         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9147         rsurface.normal3f  = rsurface.modelnormal3f;
9148         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9149         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9150         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9151 }
9152
9153 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)
9154 {
9155         rsurface.entity = r_refdef.scene.worldentity;
9156         rsurface.skeleton = NULL;
9157         rsurface.ent_skinnum = 0;
9158         rsurface.ent_qwskin = -1;
9159         rsurface.ent_shadertime = shadertime;
9160         rsurface.ent_flags = entflags;
9161         rsurface.modelnum_vertices = numvertices;
9162         rsurface.modelnum_triangles = numtriangles;
9163         if (rsurface.array_size < rsurface.modelnum_vertices)
9164                 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
9165         rsurface.matrix = *matrix;
9166         rsurface.inversematrix = *inversematrix;
9167         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9168         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9169         R_EntityMatrix(&rsurface.matrix);
9170         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9171         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9172         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9173         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9174         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9175         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9176         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9177         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9178         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9179         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9180         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9181         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
9182         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);
9183         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9184         rsurface.frameblend[0].lerp = 1;
9185         rsurface.ent_alttextures = false;
9186         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9187         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9188         if (wanttangents)
9189         {
9190                 rsurface.modelvertex3f = vertex3f;
9191                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
9192                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
9193                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9194         }
9195         else if (wantnormals)
9196         {
9197                 rsurface.modelvertex3f = vertex3f;
9198                 rsurface.modelsvector3f = NULL;
9199                 rsurface.modeltvector3f = NULL;
9200                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9201         }
9202         else
9203         {
9204                 rsurface.modelvertex3f = vertex3f;
9205                 rsurface.modelsvector3f = NULL;
9206                 rsurface.modeltvector3f = NULL;
9207                 rsurface.modelnormal3f = NULL;
9208         }
9209         rsurface.modelvertex3f_bufferobject = 0;
9210         rsurface.modelvertex3f_bufferoffset = 0;
9211         rsurface.modelsvector3f_bufferobject = 0;
9212         rsurface.modelsvector3f_bufferoffset = 0;
9213         rsurface.modeltvector3f_bufferobject = 0;
9214         rsurface.modeltvector3f_bufferoffset = 0;
9215         rsurface.modelnormal3f_bufferobject = 0;
9216         rsurface.modelnormal3f_bufferoffset = 0;
9217         rsurface.generatedvertex = true;
9218         rsurface.modellightmapcolor4f  = color4f;
9219         rsurface.modellightmapcolor4f_bufferobject = 0;
9220         rsurface.modellightmapcolor4f_bufferoffset = 0;
9221         rsurface.modeltexcoordtexture2f  = texcoord2f;
9222         rsurface.modeltexcoordtexture2f_bufferobject = 0;
9223         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9224         rsurface.modeltexcoordlightmap2f  = NULL;
9225         rsurface.modeltexcoordlightmap2f_bufferobject = 0;
9226         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9227         rsurface.modelelement3i = element3i;
9228         rsurface.modelelement3s = element3s;
9229         rsurface.modelelement3i_bufferobject = 0;
9230         rsurface.modelelement3s_bufferobject = 0;
9231         rsurface.modellightmapoffsets = NULL;
9232         rsurface.modelsurfaces = NULL;
9233         rsurface.vertex3f  = rsurface.modelvertex3f;
9234         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9235         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9236         rsurface.svector3f = rsurface.modelsvector3f;
9237         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9238         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9239         rsurface.tvector3f = rsurface.modeltvector3f;
9240         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9241         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9242         rsurface.normal3f  = rsurface.modelnormal3f;
9243         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9244         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9245         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9246
9247         if (rsurface.modelnum_vertices && rsurface.modelelement3i)
9248         {
9249                 if ((wantnormals || wanttangents) && !normal3f)
9250                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9251                 if (wanttangents && !svector3f)
9252                         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);
9253         }
9254 }
9255
9256 float RSurf_FogPoint(const float *v)
9257 {
9258         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9259         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9260         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9261         float FogHeightFade = r_refdef.fogheightfade;
9262         float fogfrac;
9263         unsigned int fogmasktableindex;
9264         if (r_refdef.fogplaneviewabove)
9265                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9266         else
9267                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9268         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9269         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9270 }
9271
9272 float RSurf_FogVertex(const float *v)
9273 {
9274         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9275         float FogPlaneViewDist = rsurface.fogplaneviewdist;
9276         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9277         float FogHeightFade = rsurface.fogheightfade;
9278         float fogfrac;
9279         unsigned int fogmasktableindex;
9280         if (r_refdef.fogplaneviewabove)
9281                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9282         else
9283                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9284         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9285         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9286 }
9287
9288 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9289 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9290 {
9291         int deformindex;
9292         int texturesurfaceindex;
9293         int i, j;
9294         float amplitude;
9295         float animpos;
9296         float scale;
9297         const float *v1, *in_tc;
9298         float *out_tc;
9299         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9300         float waveparms[4];
9301         q3shaderinfo_deform_t *deform;
9302         // 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
9303         if (rsurface.generatedvertex)
9304         {
9305                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
9306                         generatenormals = true;
9307                 for (i = 0;i < Q3MAXDEFORMS;i++)
9308                 {
9309                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
9310                         {
9311                                 generatetangents = true;
9312                                 generatenormals = true;
9313                         }
9314                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
9315                                 generatenormals = true;
9316                 }
9317                 if (generatenormals && !rsurface.modelnormal3f)
9318                 {
9319                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9320                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
9321                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
9322                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9323                 }
9324                 if (generatetangents && !rsurface.modelsvector3f)
9325                 {
9326                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9327                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
9328                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
9329                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9330                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
9331                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
9332                         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);
9333                 }
9334         }
9335         rsurface.vertex3f  = rsurface.modelvertex3f;
9336         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9337         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9338         rsurface.svector3f = rsurface.modelsvector3f;
9339         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9340         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9341         rsurface.tvector3f = rsurface.modeltvector3f;
9342         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9343         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9344         rsurface.normal3f  = rsurface.modelnormal3f;
9345         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9346         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9347         // if vertices are deformed (sprite flares and things in maps, possibly
9348         // water waves, bulges and other deformations), generate them into
9349         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
9350         // (may be static model data or generated data for an animated model, or
9351         //  the previous deform pass)
9352         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
9353         {
9354                 switch (deform->deform)
9355                 {
9356                 default:
9357                 case Q3DEFORM_PROJECTIONSHADOW:
9358                 case Q3DEFORM_TEXT0:
9359                 case Q3DEFORM_TEXT1:
9360                 case Q3DEFORM_TEXT2:
9361                 case Q3DEFORM_TEXT3:
9362                 case Q3DEFORM_TEXT4:
9363                 case Q3DEFORM_TEXT5:
9364                 case Q3DEFORM_TEXT6:
9365                 case Q3DEFORM_TEXT7:
9366                 case Q3DEFORM_NONE:
9367                         break;
9368                 case Q3DEFORM_AUTOSPRITE:
9369                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9370                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9371                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9372                         VectorNormalize(newforward);
9373                         VectorNormalize(newright);
9374                         VectorNormalize(newup);
9375                         // make deformed versions of only the model vertices used by the specified surfaces
9376                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9377                         {
9378                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9379                                 // a single autosprite surface can contain multiple sprites...
9380                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9381                                 {
9382                                         VectorClear(center);
9383                                         for (i = 0;i < 4;i++)
9384                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9385                                         VectorScale(center, 0.25f, center);
9386                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
9387                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
9388                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
9389                                         for (i = 0;i < 4;i++)
9390                                         {
9391                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
9392                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9393                                         }
9394                                 }
9395                                 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);
9396                                 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);
9397                         }
9398                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9399                         rsurface.vertex3f_bufferobject = 0;
9400                         rsurface.vertex3f_bufferoffset = 0;
9401                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9402                         rsurface.svector3f_bufferobject = 0;
9403                         rsurface.svector3f_bufferoffset = 0;
9404                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9405                         rsurface.tvector3f_bufferobject = 0;
9406                         rsurface.tvector3f_bufferoffset = 0;
9407                         rsurface.normal3f = rsurface.array_deformednormal3f;
9408                         rsurface.normal3f_bufferobject = 0;
9409                         rsurface.normal3f_bufferoffset = 0;
9410                         break;
9411                 case Q3DEFORM_AUTOSPRITE2:
9412                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9413                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9414                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9415                         VectorNormalize(newforward);
9416                         VectorNormalize(newright);
9417                         VectorNormalize(newup);
9418                         // make deformed versions of only the model vertices used by the specified surfaces
9419                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9420                         {
9421                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9422                                 const float *v1, *v2;
9423                                 vec3_t start, end;
9424                                 float f, l;
9425                                 struct
9426                                 {
9427                                         float length2;
9428                                         const float *v1;
9429                                         const float *v2;
9430                                 }
9431                                 shortest[2];
9432                                 memset(shortest, 0, sizeof(shortest));
9433                                 // a single autosprite surface can contain multiple sprites...
9434                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9435                                 {
9436                                         VectorClear(center);
9437                                         for (i = 0;i < 4;i++)
9438                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9439                                         VectorScale(center, 0.25f, center);
9440                                         // find the two shortest edges, then use them to define the
9441                                         // axis vectors for rotating around the central axis
9442                                         for (i = 0;i < 6;i++)
9443                                         {
9444                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
9445                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
9446 #if 0
9447                                                 Debug_PolygonBegin(NULL, 0);
9448                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
9449                                                 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);
9450                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
9451                                                 Debug_PolygonEnd();
9452 #endif
9453                                                 l = VectorDistance2(v1, v2);
9454                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9455                                                 if (v1[2] != v2[2])
9456                                                         l += (1.0f / 1024.0f);
9457                                                 if (shortest[0].length2 > l || i == 0)
9458                                                 {
9459                                                         shortest[1] = shortest[0];
9460                                                         shortest[0].length2 = l;
9461                                                         shortest[0].v1 = v1;
9462                                                         shortest[0].v2 = v2;
9463                                                 }
9464                                                 else if (shortest[1].length2 > l || i == 1)
9465                                                 {
9466                                                         shortest[1].length2 = l;
9467                                                         shortest[1].v1 = v1;
9468                                                         shortest[1].v2 = v2;
9469                                                 }
9470                                         }
9471                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9472                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9473 #if 0
9474                                         Debug_PolygonBegin(NULL, 0);
9475                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
9476                                         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);
9477                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
9478                                         Debug_PolygonEnd();
9479 #endif
9480                                         // this calculates the right vector from the shortest edge
9481                                         // and the up vector from the edge midpoints
9482                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9483                                         VectorNormalize(right);
9484                                         VectorSubtract(end, start, up);
9485                                         VectorNormalize(up);
9486                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9487                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9488                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9489                                         VectorNegate(forward, forward);
9490                                         VectorReflect(forward, 0, up, forward);
9491                                         VectorNormalize(forward);
9492                                         CrossProduct(up, forward, newright);
9493                                         VectorNormalize(newright);
9494 #if 0
9495                                         Debug_PolygonBegin(NULL, 0);
9496                                         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);
9497                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
9498                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
9499                                         Debug_PolygonEnd();
9500 #endif
9501 #if 0
9502                                         Debug_PolygonBegin(NULL, 0);
9503                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
9504                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
9505                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
9506                                         Debug_PolygonEnd();
9507 #endif
9508                                         // rotate the quad around the up axis vector, this is made
9509                                         // especially easy by the fact we know the quad is flat,
9510                                         // so we only have to subtract the center position and
9511                                         // measure distance along the right vector, and then
9512                                         // multiply that by the newright vector and add back the
9513                                         // center position
9514                                         // we also need to subtract the old position to undo the
9515                                         // displacement from the center, which we do with a
9516                                         // DotProduct, the subtraction/addition of center is also
9517                                         // optimized into DotProducts here
9518                                         l = DotProduct(right, center);
9519                                         for (i = 0;i < 4;i++)
9520                                         {
9521                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
9522                                                 f = DotProduct(right, v1) - l;
9523                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9524                                         }
9525                                 }
9526                                 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);
9527                                 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);
9528                         }
9529                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9530                         rsurface.vertex3f_bufferobject = 0;
9531                         rsurface.vertex3f_bufferoffset = 0;
9532                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9533                         rsurface.svector3f_bufferobject = 0;
9534                         rsurface.svector3f_bufferoffset = 0;
9535                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9536                         rsurface.tvector3f_bufferobject = 0;
9537                         rsurface.tvector3f_bufferoffset = 0;
9538                         rsurface.normal3f = rsurface.array_deformednormal3f;
9539                         rsurface.normal3f_bufferobject = 0;
9540                         rsurface.normal3f_bufferoffset = 0;
9541                         break;
9542                 case Q3DEFORM_NORMAL:
9543                         // deform the normals to make reflections wavey
9544                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9545                         {
9546                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9547                                 for (j = 0;j < surface->num_vertices;j++)
9548                                 {
9549                                         float vertex[3];
9550                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
9551                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
9552                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
9553                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9554                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9555                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9556                                         VectorNormalize(normal);
9557                                 }
9558                                 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);
9559                         }
9560                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9561                         rsurface.svector3f_bufferobject = 0;
9562                         rsurface.svector3f_bufferoffset = 0;
9563                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9564                         rsurface.tvector3f_bufferobject = 0;
9565                         rsurface.tvector3f_bufferoffset = 0;
9566                         rsurface.normal3f = rsurface.array_deformednormal3f;
9567                         rsurface.normal3f_bufferobject = 0;
9568                         rsurface.normal3f_bufferoffset = 0;
9569                         break;
9570                 case Q3DEFORM_WAVE:
9571                         // deform vertex array to make wavey water and flags and such
9572                         waveparms[0] = deform->waveparms[0];
9573                         waveparms[1] = deform->waveparms[1];
9574                         waveparms[2] = deform->waveparms[2];
9575                         waveparms[3] = deform->waveparms[3];
9576                         // this is how a divisor of vertex influence on deformation
9577                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9578                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9579                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9580                         {
9581                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9582                                 for (j = 0;j < surface->num_vertices;j++)
9583                                 {
9584                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
9585                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9586                                         // if the wavefunc depends on time, evaluate it per-vertex
9587                                         if (waveparms[3])
9588                                         {
9589                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
9590                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9591                                         }
9592                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9593                                 }
9594                         }
9595                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9596                         rsurface.vertex3f_bufferobject = 0;
9597                         rsurface.vertex3f_bufferoffset = 0;
9598                         break;
9599                 case Q3DEFORM_BULGE:
9600                         // deform vertex array to make the surface have moving bulges
9601                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9602                         {
9603                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9604                                 for (j = 0;j < surface->num_vertices;j++)
9605                                 {
9606                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
9607                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9608                                 }
9609                         }
9610                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9611                         rsurface.vertex3f_bufferobject = 0;
9612                         rsurface.vertex3f_bufferoffset = 0;
9613                         break;
9614                 case Q3DEFORM_MOVE:
9615                         // deform vertex array
9616                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9617                         VectorScale(deform->parms, scale, waveparms);
9618                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9619                         {
9620                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9621                                 for (j = 0;j < surface->num_vertices;j++)
9622                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9623                         }
9624                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9625                         rsurface.vertex3f_bufferobject = 0;
9626                         rsurface.vertex3f_bufferoffset = 0;
9627                         break;
9628                 }
9629         }
9630         // generate texcoords based on the chosen texcoord source
9631         switch(rsurface.texture->tcgen.tcgen)
9632         {
9633         default:
9634         case Q3TCGEN_TEXTURE:
9635                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
9636                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
9637                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9638                 break;
9639         case Q3TCGEN_LIGHTMAP:
9640                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
9641                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
9642                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
9643                 break;
9644         case Q3TCGEN_VECTOR:
9645                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9646                 {
9647                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9648                         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)
9649                         {
9650                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
9651                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
9652                         }
9653                 }
9654                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9655                 rsurface.texcoordtexture2f_bufferobject  = 0;
9656                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9657                 break;
9658         case Q3TCGEN_ENVIRONMENT:
9659                 // make environment reflections using a spheremap
9660                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9661                 {
9662                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9663                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
9664                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
9665                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
9666                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
9667                         {
9668                                 // identical to Q3A's method, but executed in worldspace so
9669                                 // carried models can be shiny too
9670
9671                                 float viewer[3], d, reflected[3], worldreflected[3];
9672
9673                                 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
9674                                 // VectorNormalize(viewer);
9675
9676                                 d = DotProduct(normal, viewer);
9677
9678                                 reflected[0] = normal[0]*2*d - viewer[0];
9679                                 reflected[1] = normal[1]*2*d - viewer[1];
9680                                 reflected[2] = normal[2]*2*d - viewer[2];
9681                                 // note: this is proportinal to viewer, so we can normalize later
9682
9683                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9684                                 VectorNormalize(worldreflected);
9685
9686                                 // note: this sphere map only uses world x and z!
9687                                 // so positive and negative y will LOOK THE SAME.
9688                                 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
9689                                 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
9690                         }
9691                 }
9692                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9693                 rsurface.texcoordtexture2f_bufferobject  = 0;
9694                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9695                 break;
9696         }
9697         // the only tcmod that needs software vertex processing is turbulent, so
9698         // check for it here and apply the changes if needed
9699         // and we only support that as the first one
9700         // (handling a mixture of turbulent and other tcmods would be problematic
9701         //  without punting it entirely to a software path)
9702         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9703         {
9704                 amplitude = rsurface.texture->tcmods[0].parms[1];
9705                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
9706                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9707                 {
9708                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9709                         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)
9710                         {
9711                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9712                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9713                         }
9714                 }
9715                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9716                 rsurface.texcoordtexture2f_bufferobject  = 0;
9717                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9718         }
9719         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
9720         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
9721         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9722         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
9723 }
9724
9725 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9726 {
9727         int i, j;
9728         const msurface_t *surface = texturesurfacelist[0];
9729         const msurface_t *surface2;
9730         int firstvertex;
9731         int endvertex;
9732         int numvertices;
9733         int numtriangles;
9734         // TODO: lock all array ranges before render, rather than on each surface
9735         if (texturenumsurfaces == 1)
9736                 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);
9737         else if (r_batchmode.integer == 2)
9738         {
9739                 #define MAXBATCHTRIANGLES 4096
9740                 int batchtriangles = 0;
9741                 static int batchelements[MAXBATCHTRIANGLES*3];
9742                 for (i = 0;i < texturenumsurfaces;i = j)
9743                 {
9744                         surface = texturesurfacelist[i];
9745                         j = i + 1;
9746                         if (surface->num_triangles > MAXBATCHTRIANGLES)
9747                         {
9748                                 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);
9749                                 continue;
9750                         }
9751                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9752                         batchtriangles = surface->num_triangles;
9753                         firstvertex = surface->num_firstvertex;
9754                         endvertex = surface->num_firstvertex + surface->num_vertices;
9755                         for (;j < texturenumsurfaces;j++)
9756                         {
9757                                 surface2 = texturesurfacelist[j];
9758                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9759                                         break;
9760                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9761                                 batchtriangles += surface2->num_triangles;
9762                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
9763                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9764                         }
9765                         surface2 = texturesurfacelist[j-1];
9766                         numvertices = endvertex - firstvertex;
9767                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9768                 }
9769         }
9770         else if (r_batchmode.integer == 1)
9771         {
9772                 for (i = 0;i < texturenumsurfaces;i = j)
9773                 {
9774                         surface = texturesurfacelist[i];
9775                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9776                                 if (texturesurfacelist[j] != surface2)
9777                                         break;
9778                         surface2 = texturesurfacelist[j-1];
9779                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9780                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9781                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9782                 }
9783         }
9784         else
9785         {
9786                 for (i = 0;i < texturenumsurfaces;i++)
9787                 {
9788                         surface = texturesurfacelist[i];
9789                         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);
9790                 }
9791         }
9792 }
9793
9794 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
9795 {
9796         switch(vid.renderpath)
9797         {
9798         case RENDERPATH_CGGL:
9799 #ifdef SUPPORTCG
9800                 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
9801                 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
9802 #endif
9803                 break;
9804         case RENDERPATH_GL20:
9805                 if (r_glsl_permutation->loc_Texture_Lightmap  >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
9806                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
9807                 break;
9808         case RENDERPATH_GL13:
9809         case RENDERPATH_GL11:
9810                 R_Mesh_TexBind(0, surface->lightmaptexture);
9811                 break;
9812         }
9813 }
9814
9815 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
9816 {
9817         // pick the closest matching water plane and bind textures
9818         int planeindex, vertexindex;
9819         float d, bestd;
9820         vec3_t vert;
9821         const float *v;
9822         r_waterstate_waterplane_t *p, *bestp;
9823         bestd = 0;
9824         bestp = NULL;
9825         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9826         {
9827                 d = 0;
9828                 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
9829                 {
9830                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9831                         d += fabs(PlaneDiff(vert, &p->plane));
9832                 }
9833                 if (bestd > d || !bestp)
9834                 {
9835                         bestd = d;
9836                         bestp = p;
9837                 }
9838         }
9839         switch(vid.renderpath)
9840         {
9841         case RENDERPATH_CGGL:
9842 #ifdef SUPPORTCG
9843                 if (r_cg_permutation->fp_Texture_Refraction) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR
9844                 if (r_cg_permutation->fp_Texture_Reflection) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR
9845 #endif
9846                 break;
9847         case RENDERPATH_GL20:
9848                 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
9849                 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
9850                 break;
9851         case RENDERPATH_GL13:
9852         case RENDERPATH_GL11:
9853                 break;
9854         }
9855 }
9856
9857 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9858 {
9859         int i;
9860         const msurface_t *surface;
9861         if (r_waterstate.renderingscene)
9862                 return;
9863         for (i = 0;i < texturenumsurfaces;i++)
9864         {
9865                 surface = texturesurfacelist[i];
9866                 RSurf_BindLightmapForSurface(surface);
9867                 RSurf_BindReflectionForSurface(surface);
9868                 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);
9869         }
9870 }
9871
9872 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9873 {
9874         int i;
9875         int j;
9876         const msurface_t *surface = texturesurfacelist[0];
9877         const msurface_t *surface2;
9878         int firstvertex;
9879         int endvertex;
9880         int numvertices;
9881         int numtriangles;
9882         if (texturenumsurfaces == 1)
9883         {
9884                 RSurf_BindLightmapForSurface(surface);
9885                 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);
9886         }
9887         else if (r_batchmode.integer == 2)
9888         {
9889 #define MAXBATCHTRIANGLES 4096
9890                 int batchtriangles = 0;
9891                 static int batchelements[MAXBATCHTRIANGLES*3];
9892                 for (i = 0;i < texturenumsurfaces;i = j)
9893                 {
9894                         surface = texturesurfacelist[i];
9895                         RSurf_BindLightmapForSurface(surface);
9896                         j = i + 1;
9897                         if (surface->num_triangles > MAXBATCHTRIANGLES)
9898                         {
9899                                 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);
9900                                 continue;
9901                         }
9902                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9903                         batchtriangles = surface->num_triangles;
9904                         firstvertex = surface->num_firstvertex;
9905                         endvertex = surface->num_firstvertex + surface->num_vertices;
9906                         for (;j < texturenumsurfaces;j++)
9907                         {
9908                                 surface2 = texturesurfacelist[j];
9909                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9910                                         break;
9911                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9912                                 batchtriangles += surface2->num_triangles;
9913                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
9914                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9915                         }
9916                         surface2 = texturesurfacelist[j-1];
9917                         numvertices = endvertex - firstvertex;
9918                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9919                 }
9920         }
9921         else if (r_batchmode.integer == 1)
9922         {
9923 #if 0
9924                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
9925                 for (i = 0;i < texturenumsurfaces;i = j)
9926                 {
9927                         surface = texturesurfacelist[i];
9928                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9929                                 if (texturesurfacelist[j] != surface2)
9930                                         break;
9931                         Con_Printf(" %i", j - i);
9932                 }
9933                 Con_Printf("\n");
9934                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
9935 #endif
9936                 for (i = 0;i < texturenumsurfaces;i = j)
9937                 {
9938                         surface = texturesurfacelist[i];
9939                         RSurf_BindLightmapForSurface(surface);
9940                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9941                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
9942                                         break;
9943 #if 0
9944                         Con_Printf(" %i", j - i);
9945 #endif
9946                         surface2 = texturesurfacelist[j-1];
9947                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9948                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9949                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9950                 }
9951 #if 0
9952                 Con_Printf("\n");
9953 #endif
9954         }
9955         else
9956         {
9957                 for (i = 0;i < texturenumsurfaces;i++)
9958                 {
9959                         surface = texturesurfacelist[i];
9960                         RSurf_BindLightmapForSurface(surface);
9961                         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);
9962                 }
9963         }
9964 }
9965
9966 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9967 {
9968         int j;
9969         int texturesurfaceindex;
9970         if (r_showsurfaces.integer == 2)
9971         {
9972                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9973                 {
9974                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9975                         for (j = 0;j < surface->num_triangles;j++)
9976                         {
9977                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
9978                                 GL_Color(f, f, f, 1);
9979                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9980                         }
9981                 }
9982         }
9983         else
9984         {
9985                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9986                 {
9987                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9988                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
9989                         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);
9990                         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);
9991                 }
9992         }
9993 }
9994
9995 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9996 {
9997         int texturesurfaceindex;
9998         int i;
9999         const float *v;
10000         float *c2;
10001         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10002         {
10003                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10004                 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)
10005                 {
10006                         c2[0] = 0.5;
10007                         c2[1] = 0.5;
10008                         c2[2] = 0.5;
10009                         c2[3] = 1;
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_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10018 {
10019         int texturesurfaceindex;
10020         int i;
10021         float f;
10022         const float *v;
10023         const float *c;
10024         float *c2;
10025         if (rsurface.lightmapcolor4f)
10026         {
10027                 // generate color arrays for the surfaces in this list
10028                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10029                 {
10030                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10031                         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)
10032                         {
10033                                 f = RSurf_FogVertex(v);
10034                                 c2[0] = c[0] * f;
10035                                 c2[1] = c[1] * f;
10036                                 c2[2] = c[2] * f;
10037                                 c2[3] = c[3];
10038                         }
10039                 }
10040         }
10041         else
10042         {
10043                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10044                 {
10045                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10046                         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)
10047                         {
10048                                 f = RSurf_FogVertex(v);
10049                                 c2[0] = f;
10050                                 c2[1] = f;
10051                                 c2[2] = f;
10052                                 c2[3] = 1;
10053                         }
10054                 }
10055         }
10056         rsurface.lightmapcolor4f = rsurface.array_color4f;
10057         rsurface.lightmapcolor4f_bufferobject = 0;
10058         rsurface.lightmapcolor4f_bufferoffset = 0;
10059 }
10060
10061 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10062 {
10063         int texturesurfaceindex;
10064         int i;
10065         float f;
10066         const float *v;
10067         const float *c;
10068         float *c2;
10069         if (!rsurface.lightmapcolor4f)
10070                 return;
10071         // generate color arrays for the surfaces in this list
10072         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10073         {
10074                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10075                 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)
10076                 {
10077                         f = RSurf_FogVertex(v);
10078                         c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10079                         c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10080                         c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10081                         c2[3] = c[3];
10082                 }
10083         }
10084         rsurface.lightmapcolor4f = rsurface.array_color4f;
10085         rsurface.lightmapcolor4f_bufferobject = 0;
10086         rsurface.lightmapcolor4f_bufferoffset = 0;
10087 }
10088
10089 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
10090 {
10091         int texturesurfaceindex;
10092         int i;
10093         const float *c;
10094         float *c2;
10095         if (!rsurface.lightmapcolor4f)
10096                 return;
10097         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10098         {
10099                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10100                 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)
10101                 {
10102                         c2[0] = c[0] * r;
10103                         c2[1] = c[1] * g;
10104                         c2[2] = c[2] * b;
10105                         c2[3] = c[3] * a;
10106                 }
10107         }
10108         rsurface.lightmapcolor4f = rsurface.array_color4f;
10109         rsurface.lightmapcolor4f_bufferobject = 0;
10110         rsurface.lightmapcolor4f_bufferoffset = 0;
10111 }
10112
10113 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10114 {
10115         int texturesurfaceindex;
10116         int i;
10117         const float *c;
10118         float *c2;
10119         if (!rsurface.lightmapcolor4f)
10120                 return;
10121         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10122         {
10123                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10124                 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)
10125                 {
10126                         c2[0] = c[0] + r_refdef.scene.ambient;
10127                         c2[1] = c[1] + r_refdef.scene.ambient;
10128                         c2[2] = c[2] + r_refdef.scene.ambient;
10129                         c2[3] = c[3];
10130                 }
10131         }
10132         rsurface.lightmapcolor4f = rsurface.array_color4f;
10133         rsurface.lightmapcolor4f_bufferobject = 0;
10134         rsurface.lightmapcolor4f_bufferoffset = 0;
10135 }
10136
10137 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10138 {
10139         // TODO: optimize
10140         rsurface.lightmapcolor4f = NULL;
10141         rsurface.lightmapcolor4f_bufferobject = 0;
10142         rsurface.lightmapcolor4f_bufferoffset = 0;
10143         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10144         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10145         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10146         GL_Color(r, g, b, a);
10147         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10148 }
10149
10150 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10151 {
10152         // TODO: optimize applyfog && applycolor case
10153         // just apply fog if necessary, and tint the fog color array if necessary
10154         rsurface.lightmapcolor4f = NULL;
10155         rsurface.lightmapcolor4f_bufferobject = 0;
10156         rsurface.lightmapcolor4f_bufferoffset = 0;
10157         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10158         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10159         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10160         GL_Color(r, g, b, a);
10161         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10162 }
10163
10164 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10165 {
10166         int texturesurfaceindex;
10167         int i;
10168         float *c;
10169         // TODO: optimize
10170         if (texturesurfacelist[0]->lightmapinfo)
10171         {
10172                 // generate color arrays for the surfaces in this list
10173                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10174                 {
10175                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10176                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
10177                         {
10178                                 if (surface->lightmapinfo->samples)
10179                                 {
10180                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
10181                                         float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
10182                                         VectorScale(lm, scale, c);
10183                                         if (surface->lightmapinfo->styles[1] != 255)
10184                                         {
10185                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
10186                                                 lm += size3;
10187                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
10188                                                 VectorMA(c, scale, lm, c);
10189                                                 if (surface->lightmapinfo->styles[2] != 255)
10190                                                 {
10191                                                         lm += size3;
10192                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
10193                                                         VectorMA(c, scale, lm, c);
10194                                                         if (surface->lightmapinfo->styles[3] != 255)
10195                                                         {
10196                                                                 lm += size3;
10197                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
10198                                                                 VectorMA(c, scale, lm, c);
10199                                                         }
10200                                                 }
10201                                         }
10202                                 }
10203                                 else
10204                                         VectorClear(c);
10205                                 c[3] = 1;
10206                         }
10207                 }
10208                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10209                 rsurface.lightmapcolor4f_bufferobject = 0;
10210                 rsurface.lightmapcolor4f_bufferoffset = 0;
10211         }
10212         else
10213         {
10214                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10215                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10216                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10217         }
10218         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10219         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10220         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10221         GL_Color(r, g, b, a);
10222         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10223 }
10224
10225 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
10226 {
10227         int texturesurfaceindex;
10228         int i;
10229         float f;
10230         float alpha;
10231         const float *v;
10232         const float *n;
10233         float *c;
10234         vec3_t ambientcolor;
10235         vec3_t diffusecolor;
10236         vec3_t lightdir;
10237         // TODO: optimize
10238         // model lighting
10239         VectorCopy(rsurface.modellight_lightdir, lightdir);
10240         f = 0.5f * r_refdef.lightmapintensity;
10241         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10242         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10243         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10244         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10245         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10246         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10247         alpha = *a;
10248         if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
10249         {
10250                 // generate color arrays for the surfaces in this list
10251                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10252                 {
10253                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10254                         int numverts = surface->num_vertices;
10255                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
10256                         n = rsurface.normal3f + 3 * surface->num_firstvertex;
10257                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
10258                         // q3-style directional shading
10259                         for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
10260                         {
10261                                 if ((f = DotProduct(n, lightdir)) > 0)
10262                                         VectorMA(ambientcolor, f, diffusecolor, c);
10263                                 else
10264                                         VectorCopy(ambientcolor, c);
10265                                 c[3] = alpha;
10266                         }
10267                 }
10268                 *r = 1;
10269                 *g = 1;
10270                 *b = 1;
10271                 *a = 1;
10272                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10273                 rsurface.lightmapcolor4f_bufferobject = 0;
10274                 rsurface.lightmapcolor4f_bufferoffset = 0;
10275                 *applycolor = false;
10276         }
10277         else
10278         {
10279                 *r = ambientcolor[0];
10280                 *g = ambientcolor[1];
10281                 *b = ambientcolor[2];
10282                 rsurface.lightmapcolor4f = NULL;
10283                 rsurface.lightmapcolor4f_bufferobject = 0;
10284                 rsurface.lightmapcolor4f_bufferoffset = 0;
10285         }
10286 }
10287
10288 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10289 {
10290         RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
10291         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10292         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10293         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10294         GL_Color(r, g, b, a);
10295         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10296 }
10297
10298 void RSurf_SetupDepthAndCulling(void)
10299 {
10300         // submodels are biased to avoid z-fighting with world surfaces that they
10301         // may be exactly overlapping (avoids z-fighting artifacts on certain
10302         // doors and things in Quake maps)
10303         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10304         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10305         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10306         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10307 }
10308
10309 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10310 {
10311         // transparent sky would be ridiculous
10312         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10313                 return;
10314         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10315         skyrenderlater = true;
10316         RSurf_SetupDepthAndCulling();
10317         GL_DepthMask(true);
10318         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10319         // skymasking on them, and Quake3 never did sky masking (unlike
10320         // software Quake and software Quake2), so disable the sky masking
10321         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10322         // and skymasking also looks very bad when noclipping outside the
10323         // level, so don't use it then either.
10324         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
10325         {
10326                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10327                 R_Mesh_ColorPointer(NULL, 0, 0);
10328                 R_Mesh_ResetTextureState();
10329                 if (skyrendermasked)
10330                 {
10331                         R_SetupShader_DepthOrShadow();
10332                         // depth-only (masking)
10333                         GL_ColorMask(0,0,0,0);
10334                         // just to make sure that braindead drivers don't draw
10335                         // anything despite that colormask...
10336                         GL_BlendFunc(GL_ZERO, GL_ONE);
10337                 }
10338                 else
10339                 {
10340                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10341                         // fog sky
10342                         GL_BlendFunc(GL_ONE, GL_ZERO);
10343                 }
10344                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10345                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10346                 if (skyrendermasked)
10347                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10348         }
10349         R_Mesh_ResetTextureState();
10350         GL_Color(1, 1, 1, 1);
10351 }
10352
10353 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10354 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10355 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10356 {
10357         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
10358                 return;
10359         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10360         if (prepass)
10361         {
10362                 // render screenspace normalmap to texture
10363                 GL_DepthMask(true);
10364                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY);
10365                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10366         }
10367         else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !r_waterstate.renderingscene)
10368         {
10369                 // render water or distortion background, then blend surface on top
10370                 GL_DepthMask(true);
10371                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
10372                 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10373                 GL_DepthMask(false);
10374                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
10375                 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10376                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10377                 else
10378                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10379         }
10380         else
10381         {
10382                 // render surface normally
10383                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10384                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
10385                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
10386                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10387                 else if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10388                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10389                 else
10390                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10391         }
10392 }
10393
10394 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10395 {
10396         // OpenGL 1.3 path - anything not completely ancient
10397         int texturesurfaceindex;
10398         qboolean applycolor;
10399         qboolean applyfog;
10400         int layerindex;
10401         const texturelayer_t *layer;
10402         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10403
10404         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10405         {
10406                 vec4_t layercolor;
10407                 int layertexrgbscale;
10408                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10409                 {
10410                         if (layerindex == 0)
10411                                 GL_AlphaTest(true);
10412                         else
10413                         {
10414                                 GL_AlphaTest(false);
10415                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10416                         }
10417                 }
10418                 GL_DepthMask(layer->depthmask && writedepth);
10419                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10420                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10421                 {
10422                         layertexrgbscale = 4;
10423                         VectorScale(layer->color, 0.25f, layercolor);
10424                 }
10425                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10426                 {
10427                         layertexrgbscale = 2;
10428                         VectorScale(layer->color, 0.5f, layercolor);
10429                 }
10430                 else
10431                 {
10432                         layertexrgbscale = 1;
10433                         VectorScale(layer->color, 1.0f, layercolor);
10434                 }
10435                 layercolor[3] = layer->color[3];
10436                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10437                 R_Mesh_ColorPointer(NULL, 0, 0);
10438                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10439                 switch (layer->type)
10440                 {
10441                 case TEXTURELAYERTYPE_LITTEXTURE:
10442                         // single-pass lightmapped texture with 2x rgbscale
10443                         R_Mesh_TexBind(0, r_texture_white);
10444                         R_Mesh_TexMatrix(0, NULL);
10445                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10446                         R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10447                         R_Mesh_TexBind(1, layer->texture);
10448                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10449                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10450                         R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10451                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10452                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10453                         else if (rsurface.uselightmaptexture)
10454                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10455                         else
10456                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10457                         break;
10458                 case TEXTURELAYERTYPE_TEXTURE:
10459                         // singletexture unlit texture with transparency support
10460                         R_Mesh_TexBind(0, layer->texture);
10461                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10462                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10463                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10464                         R_Mesh_TexBind(1, 0);
10465                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10466                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10467                         break;
10468                 case TEXTURELAYERTYPE_FOG:
10469                         // singletexture fogging
10470                         if (layer->texture)
10471                         {
10472                                 R_Mesh_TexBind(0, layer->texture);
10473                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10474                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10475                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10476                         }
10477                         else
10478                         {
10479                                 R_Mesh_TexBind(0, 0);
10480                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10481                         }
10482                         R_Mesh_TexBind(1, 0);
10483                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10484                         // generate a color array for the fog pass
10485                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10486                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10487                         {
10488                                 int i;
10489                                 float f;
10490                                 const float *v;
10491                                 float *c;
10492                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10493                                 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)
10494                                 {
10495                                         f = 1 - RSurf_FogVertex(v);
10496                                         c[0] = layercolor[0];
10497                                         c[1] = layercolor[1];
10498                                         c[2] = layercolor[2];
10499                                         c[3] = f * layercolor[3];
10500                                 }
10501                         }
10502                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10503                         break;
10504                 default:
10505                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10506                 }
10507         }
10508         CHECKGLERROR
10509         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10510         {
10511                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10512                 GL_AlphaTest(false);
10513         }
10514 }
10515
10516 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10517 {
10518         // OpenGL 1.1 - crusty old voodoo path
10519         int texturesurfaceindex;
10520         qboolean applyfog;
10521         int layerindex;
10522         const texturelayer_t *layer;
10523         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10524
10525         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10526         {
10527                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10528                 {
10529                         if (layerindex == 0)
10530                                 GL_AlphaTest(true);
10531                         else
10532                         {
10533                                 GL_AlphaTest(false);
10534                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10535                         }
10536                 }
10537                 GL_DepthMask(layer->depthmask && writedepth);
10538                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10539                 R_Mesh_ColorPointer(NULL, 0, 0);
10540                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10541                 switch (layer->type)
10542                 {
10543                 case TEXTURELAYERTYPE_LITTEXTURE:
10544                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10545                         {
10546                                 // two-pass lit texture with 2x rgbscale
10547                                 // first the lightmap pass
10548                                 R_Mesh_TexBind(0, r_texture_white);
10549                                 R_Mesh_TexMatrix(0, NULL);
10550                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10551                                 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10552                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10553                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10554                                 else if (rsurface.uselightmaptexture)
10555                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10556                                 else
10557                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10558                                 // then apply the texture to it
10559                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10560                                 R_Mesh_TexBind(0, layer->texture);
10561                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10562                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10563                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10564                                 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);
10565                         }
10566                         else
10567                         {
10568                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10569                                 R_Mesh_TexBind(0, layer->texture);
10570                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10571                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10572                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10573                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10574                                         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);
10575                                 else
10576                                         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);
10577                         }
10578                         break;
10579                 case TEXTURELAYERTYPE_TEXTURE:
10580                         // singletexture unlit texture with transparency support
10581                         R_Mesh_TexBind(0, layer->texture);
10582                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10583                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10584                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10585                         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);
10586                         break;
10587                 case TEXTURELAYERTYPE_FOG:
10588                         // singletexture fogging
10589                         if (layer->texture)
10590                         {
10591                                 R_Mesh_TexBind(0, layer->texture);
10592                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10593                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10594                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10595                         }
10596                         else
10597                         {
10598                                 R_Mesh_TexBind(0, 0);
10599                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10600                         }
10601                         // generate a color array for the fog pass
10602                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10603                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10604                         {
10605                                 int i;
10606                                 float f;
10607                                 const float *v;
10608                                 float *c;
10609                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10610                                 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)
10611                                 {
10612                                         f = 1 - RSurf_FogVertex(v);
10613                                         c[0] = layer->color[0];
10614                                         c[1] = layer->color[1];
10615                                         c[2] = layer->color[2];
10616                                         c[3] = f * layer->color[3];
10617                                 }
10618                         }
10619                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10620                         break;
10621                 default:
10622                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10623                 }
10624         }
10625         CHECKGLERROR
10626         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10627         {
10628                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10629                 GL_AlphaTest(false);
10630         }
10631 }
10632
10633 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10634 {
10635         float c[4];
10636
10637         GL_AlphaTest(false);
10638         R_Mesh_ColorPointer(NULL, 0, 0);
10639         R_Mesh_ResetTextureState();
10640         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10641
10642         if(rsurface.texture && rsurface.texture->currentskinframe)
10643         {
10644                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10645                 c[3] *= rsurface.texture->currentalpha;
10646         }
10647         else
10648         {
10649                 c[0] = 1;
10650                 c[1] = 0;
10651                 c[2] = 1;
10652                 c[3] = 1;
10653         }
10654
10655         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10656         {
10657                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10658                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10659                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10660         }
10661
10662         // brighten it up (as texture value 127 means "unlit")
10663         c[0] *= 2 * r_refdef.view.colorscale;
10664         c[1] *= 2 * r_refdef.view.colorscale;
10665         c[2] *= 2 * r_refdef.view.colorscale;
10666
10667         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10668                 c[3] *= r_wateralpha.value;
10669
10670         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10671         {
10672                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10673                 GL_DepthMask(false);
10674         }
10675         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10676         {
10677                 GL_BlendFunc(GL_ONE, GL_ONE);
10678                 GL_DepthMask(false);
10679         }
10680         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10681         {
10682                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10683                 GL_DepthMask(false);
10684         }
10685         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10686         {
10687                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10688                 GL_DepthMask(false);
10689         }
10690         else
10691         {
10692                 GL_BlendFunc(GL_ONE, GL_ZERO);
10693                 GL_DepthMask(writedepth);
10694         }
10695
10696         rsurface.lightmapcolor4f = NULL;
10697
10698         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10699         {
10700                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10701
10702                 rsurface.lightmapcolor4f = NULL;
10703                 rsurface.lightmapcolor4f_bufferobject = 0;
10704                 rsurface.lightmapcolor4f_bufferoffset = 0;
10705         }
10706         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10707         {
10708                 qboolean applycolor = true;
10709                 float one = 1.0;
10710
10711                 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10712
10713                 r_refdef.lightmapintensity = 1;
10714                 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
10715                 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10716         }
10717         else
10718         {
10719                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10720
10721                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10722                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10723                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10724         }
10725
10726         if(!rsurface.lightmapcolor4f)
10727                 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
10728
10729         RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
10730         RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
10731         if(r_refdef.fogenabled)
10732                 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
10733
10734         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10735         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10736 }
10737
10738 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10739 {
10740         CHECKGLERROR
10741         RSurf_SetupDepthAndCulling();
10742         if (r_showsurfaces.integer == 3 && !prepass)
10743         {
10744                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10745                 return;
10746         }
10747         switch (vid.renderpath)
10748         {
10749         case RENDERPATH_GL20:
10750         case RENDERPATH_CGGL:
10751                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10752                 break;
10753         case RENDERPATH_GL13:
10754                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10755                 break;
10756         case RENDERPATH_GL11:
10757                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10758                 break;
10759         }
10760         CHECKGLERROR
10761 }
10762
10763 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10764 {
10765         CHECKGLERROR
10766         RSurf_SetupDepthAndCulling();
10767         if (r_showsurfaces.integer == 3 && !prepass)
10768         {
10769                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10770                 return;
10771         }
10772         switch (vid.renderpath)
10773         {
10774         case RENDERPATH_GL20:
10775         case RENDERPATH_CGGL:
10776                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10777                 break;
10778         case RENDERPATH_GL13:
10779                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10780                 break;
10781         case RENDERPATH_GL11:
10782                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10783                 break;
10784         }
10785         CHECKGLERROR
10786 }
10787
10788 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10789 {
10790         int i, j;
10791         int texturenumsurfaces, endsurface;
10792         texture_t *texture;
10793         const msurface_t *surface;
10794         const msurface_t *texturesurfacelist[256];
10795
10796         // if the model is static it doesn't matter what value we give for
10797         // wantnormals and wanttangents, so this logic uses only rules applicable
10798         // to a model, knowing that they are meaningless otherwise
10799         if (ent == r_refdef.scene.worldentity)
10800                 RSurf_ActiveWorldEntity();
10801         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10802                 RSurf_ActiveModelEntity(ent, false, false, false);
10803         else
10804         {
10805                 switch (vid.renderpath)
10806                 {
10807                 case RENDERPATH_GL20:
10808                 case RENDERPATH_CGGL:
10809                         RSurf_ActiveModelEntity(ent, true, true, false);
10810                         break;
10811                 case RENDERPATH_GL13:
10812                 case RENDERPATH_GL11:
10813                         RSurf_ActiveModelEntity(ent, true, false, false);
10814                         break;
10815                 }
10816         }
10817
10818         if (r_transparentdepthmasking.integer)
10819         {
10820                 qboolean setup = false;
10821                 for (i = 0;i < numsurfaces;i = j)
10822                 {
10823                         j = i + 1;
10824                         surface = rsurface.modelsurfaces + surfacelist[i];
10825                         texture = surface->texture;
10826                         rsurface.texture = R_GetCurrentTexture(texture);
10827                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10828                         // scan ahead until we find a different texture
10829                         endsurface = min(i + 1024, numsurfaces);
10830                         texturenumsurfaces = 0;
10831                         texturesurfacelist[texturenumsurfaces++] = surface;
10832                         for (;j < endsurface;j++)
10833                         {
10834                                 surface = rsurface.modelsurfaces + surfacelist[j];
10835                                 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10836                                         break;
10837                                 texturesurfacelist[texturenumsurfaces++] = surface;
10838                         }
10839                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10840                                 continue;
10841                         // render the range of surfaces as depth
10842                         if (!setup)
10843                         {
10844                                 setup = true;
10845                                 GL_ColorMask(0,0,0,0);
10846                                 GL_Color(1,1,1,1);
10847                                 GL_DepthTest(true);
10848                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10849                                 GL_DepthMask(true);
10850                                 GL_AlphaTest(false);
10851                                 R_Mesh_ColorPointer(NULL, 0, 0);
10852                                 R_Mesh_ResetTextureState();
10853                                 R_SetupShader_DepthOrShadow();
10854                         }
10855                         RSurf_SetupDepthAndCulling();
10856                         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10857                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10858                 }
10859                 if (setup)
10860                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10861         }
10862
10863         for (i = 0;i < numsurfaces;i = j)
10864         {
10865                 j = i + 1;
10866                 surface = rsurface.modelsurfaces + surfacelist[i];
10867                 texture = surface->texture;
10868                 rsurface.texture = R_GetCurrentTexture(texture);
10869                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10870                 // scan ahead until we find a different texture
10871                 endsurface = min(i + 1024, numsurfaces);
10872                 texturenumsurfaces = 0;
10873                 texturesurfacelist[texturenumsurfaces++] = surface;
10874                 for (;j < endsurface;j++)
10875                 {
10876                         surface = rsurface.modelsurfaces + surfacelist[j];
10877                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10878                                 break;
10879                         texturesurfacelist[texturenumsurfaces++] = surface;
10880                 }
10881                 // render the range of surfaces
10882                 if (ent == r_refdef.scene.worldentity)
10883                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10884                 else
10885                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10886         }
10887         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10888         GL_AlphaTest(false);
10889 }
10890
10891 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10892 {
10893         // transparent surfaces get pushed off into the transparent queue
10894         int surfacelistindex;
10895         const msurface_t *surface;
10896         vec3_t tempcenter, center;
10897         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10898         {
10899                 surface = texturesurfacelist[surfacelistindex];
10900                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10901                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10902                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10903                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10904                 if (queueentity->transparent_offset) // transparent offset
10905                 {
10906                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10907                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10908                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10909                 }
10910                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10911         }
10912 }
10913
10914 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10915 {
10916         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10917         CHECKGLERROR
10918         if (depthonly)
10919         {
10920                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10921                         return;
10922                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10923                         return;
10924                 RSurf_SetupDepthAndCulling();
10925                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10926                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10927         }
10928         else if (prepass)
10929         {
10930                 if (!rsurface.texture->currentnumlayers)
10931                         return;
10932                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10933                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10934                 else
10935                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10936         }
10937         else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
10938         {
10939                 RSurf_SetupDepthAndCulling();
10940                 GL_AlphaTest(false);
10941                 R_Mesh_ColorPointer(NULL, 0, 0);
10942                 R_Mesh_ResetTextureState();
10943                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10944                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10945                 GL_DepthMask(true);
10946                 GL_BlendFunc(GL_ONE, GL_ZERO);
10947                 GL_Color(0, 0, 0, 1);
10948                 GL_DepthTest(writedepth);
10949                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10950         }
10951         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
10952         {
10953                 RSurf_SetupDepthAndCulling();
10954                 GL_AlphaTest(false);
10955                 R_Mesh_ColorPointer(NULL, 0, 0);
10956                 R_Mesh_ResetTextureState();
10957                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10958                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10959                 GL_DepthMask(true);
10960                 GL_BlendFunc(GL_ONE, GL_ZERO);
10961                 GL_DepthTest(true);
10962                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
10963         }
10964         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
10965                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10966         else if (!rsurface.texture->currentnumlayers)
10967                 return;
10968         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10969         {
10970                 // in the deferred case, transparent surfaces were queued during prepass
10971                 if (!r_shadow_usingdeferredprepass)
10972                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10973         }
10974         else
10975         {
10976                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10977                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10978         }
10979         CHECKGLERROR
10980 }
10981
10982 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10983 {
10984         int i, j;
10985         texture_t *texture;
10986         // break the surface list down into batches by texture and use of lightmapping
10987         for (i = 0;i < numsurfaces;i = j)
10988         {
10989                 j = i + 1;
10990                 // texture is the base texture pointer, rsurface.texture is the
10991                 // current frame/skin the texture is directing us to use (for example
10992                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10993                 // use skin 1 instead)
10994                 texture = surfacelist[i]->texture;
10995                 rsurface.texture = R_GetCurrentTexture(texture);
10996                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
10997                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10998                 {
10999                         // if this texture is not the kind we want, skip ahead to the next one
11000                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11001                                 ;
11002                         continue;
11003                 }
11004                 // simply scan ahead until we find a different texture or lightmap state
11005                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11006                         ;
11007                 // render the range of surfaces
11008                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11009         }
11010 }
11011
11012 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
11013 {
11014         CHECKGLERROR
11015         if (depthonly)
11016         {
11017                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11018                         return;
11019                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11020                         return;
11021                 RSurf_SetupDepthAndCulling();
11022                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11023                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11024         }
11025         else if (prepass)
11026         {
11027                 if (!rsurface.texture->currentnumlayers)
11028                         return;
11029                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11030                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11031                 else
11032                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11033         }
11034         else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
11035         {
11036                 RSurf_SetupDepthAndCulling();
11037                 GL_AlphaTest(false);
11038                 R_Mesh_ColorPointer(NULL, 0, 0);
11039                 R_Mesh_ResetTextureState();
11040                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11041                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11042                 GL_DepthMask(true);
11043                 GL_BlendFunc(GL_ONE, GL_ZERO);
11044                 GL_Color(0, 0, 0, 1);
11045                 GL_DepthTest(writedepth);
11046                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11047         }
11048         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11049         {
11050                 RSurf_SetupDepthAndCulling();
11051                 GL_AlphaTest(false);
11052                 R_Mesh_ColorPointer(NULL, 0, 0);
11053                 R_Mesh_ResetTextureState();
11054                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11055                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11056                 GL_DepthMask(true);
11057                 GL_BlendFunc(GL_ONE, GL_ZERO);
11058                 GL_DepthTest(true);
11059                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11060         }
11061         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11062                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11063         else if (!rsurface.texture->currentnumlayers)
11064                 return;
11065         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11066         {
11067                 // in the deferred case, transparent surfaces were queued during prepass
11068                 if (!r_shadow_usingdeferredprepass)
11069                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11070         }
11071         else
11072         {
11073                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11074                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11075         }
11076         CHECKGLERROR
11077 }
11078
11079 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11080 {
11081         int i, j;
11082         texture_t *texture;
11083         // break the surface list down into batches by texture and use of lightmapping
11084         for (i = 0;i < numsurfaces;i = j)
11085         {
11086                 j = i + 1;
11087                 // texture is the base texture pointer, rsurface.texture is the
11088                 // current frame/skin the texture is directing us to use (for example
11089                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11090                 // use skin 1 instead)
11091                 texture = surfacelist[i]->texture;
11092                 rsurface.texture = R_GetCurrentTexture(texture);
11093                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11094                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11095                 {
11096                         // if this texture is not the kind we want, skip ahead to the next one
11097                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11098                                 ;
11099                         continue;
11100                 }
11101                 // simply scan ahead until we find a different texture or lightmap state
11102                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11103                         ;
11104                 // render the range of surfaces
11105                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
11106         }
11107 }
11108
11109 float locboxvertex3f[6*4*3] =
11110 {
11111         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11112         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11113         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11114         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11115         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11116         1,0,0, 0,0,0, 0,1,0, 1,1,0
11117 };
11118
11119 unsigned short locboxelements[6*2*3] =
11120 {
11121          0, 1, 2, 0, 2, 3,
11122          4, 5, 6, 4, 6, 7,
11123          8, 9,10, 8,10,11,
11124         12,13,14, 12,14,15,
11125         16,17,18, 16,18,19,
11126         20,21,22, 20,22,23
11127 };
11128
11129 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11130 {
11131         int i, j;
11132         cl_locnode_t *loc = (cl_locnode_t *)ent;
11133         vec3_t mins, size;
11134         float vertex3f[6*4*3];
11135         CHECKGLERROR
11136         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11137         GL_DepthMask(false);
11138         GL_DepthRange(0, 1);
11139         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11140         GL_DepthTest(true);
11141         GL_CullFace(GL_NONE);
11142         R_EntityMatrix(&identitymatrix);
11143
11144         R_Mesh_VertexPointer(vertex3f, 0, 0);
11145         R_Mesh_ColorPointer(NULL, 0, 0);
11146         R_Mesh_ResetTextureState();
11147         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11148
11149         i = surfacelist[0];
11150         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11151                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11152                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11153                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11154
11155         if (VectorCompare(loc->mins, loc->maxs))
11156         {
11157                 VectorSet(size, 2, 2, 2);
11158                 VectorMA(loc->mins, -0.5f, size, mins);
11159         }
11160         else
11161         {
11162                 VectorCopy(loc->mins, mins);
11163                 VectorSubtract(loc->maxs, loc->mins, size);
11164         }
11165
11166         for (i = 0;i < 6*4*3;)
11167                 for (j = 0;j < 3;j++, i++)
11168                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11169
11170         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
11171 }
11172
11173 void R_DrawLocs(void)
11174 {
11175         int index;
11176         cl_locnode_t *loc, *nearestloc;
11177         vec3_t center;
11178         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11179         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11180         {
11181                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11182                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11183         }
11184 }
11185
11186 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11187 {
11188         if (decalsystem->decals)
11189                 Mem_Free(decalsystem->decals);
11190         memset(decalsystem, 0, sizeof(*decalsystem));
11191 }
11192
11193 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)
11194 {
11195         tridecal_t *decal;
11196         tridecal_t *decals;
11197         int i;
11198         int maxdecals;
11199
11200         // expand or initialize the system
11201         if (decalsystem->maxdecals <= decalsystem->numdecals)
11202         {
11203                 decalsystem_t old = *decalsystem;
11204                 qboolean useshortelements;
11205                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11206                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11207                 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)));
11208                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11209                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11210                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11211                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11212                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11213                 if (decalsystem->numdecals)
11214                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11215                 if (old.decals)
11216                         Mem_Free(old.decals);
11217                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11218                         decalsystem->element3i[i] = i;
11219                 if (useshortelements)
11220                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11221                                 decalsystem->element3s[i] = i;
11222         }
11223
11224         // grab a decal and search for another free slot for the next one
11225         maxdecals = decalsystem->maxdecals;
11226         decals = decalsystem->decals;
11227         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11228         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
11229                 ;
11230         decalsystem->freedecal = i;
11231         if (decalsystem->numdecals <= i)
11232                 decalsystem->numdecals = i + 1;
11233
11234         // initialize the decal
11235         decal->lived = 0;
11236         decal->triangleindex = triangleindex;
11237         decal->surfaceindex = surfaceindex;
11238         decal->decalsequence = decalsequence;
11239         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
11240         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
11241         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
11242         decal->color4ub[0][3] = 255;
11243         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
11244         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
11245         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
11246         decal->color4ub[1][3] = 255;
11247         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
11248         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
11249         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
11250         decal->color4ub[2][3] = 255;
11251         decal->vertex3f[0][0] = v0[0];
11252         decal->vertex3f[0][1] = v0[1];
11253         decal->vertex3f[0][2] = v0[2];
11254         decal->vertex3f[1][0] = v1[0];
11255         decal->vertex3f[1][1] = v1[1];
11256         decal->vertex3f[1][2] = v1[2];
11257         decal->vertex3f[2][0] = v2[0];
11258         decal->vertex3f[2][1] = v2[1];
11259         decal->vertex3f[2][2] = v2[2];
11260         decal->texcoord2f[0][0] = t0[0];
11261         decal->texcoord2f[0][1] = t0[1];
11262         decal->texcoord2f[1][0] = t1[0];
11263         decal->texcoord2f[1][1] = t1[1];
11264         decal->texcoord2f[2][0] = t2[0];
11265         decal->texcoord2f[2][1] = t2[1];
11266 }
11267
11268 extern cvar_t cl_decals_bias;
11269 extern cvar_t cl_decals_models;
11270 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11271 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)
11272 {
11273         matrix4x4_t projection;
11274         decalsystem_t *decalsystem;
11275         qboolean dynamic;
11276         dp_model_t *model;
11277         const float *vertex3f;
11278         const msurface_t *surface;
11279         const msurface_t *surfaces;
11280         const int *surfacelist;
11281         const texture_t *texture;
11282         int numvertices;
11283         int numtriangles;
11284         int numsurfacelist;
11285         int surfacelistindex;
11286         int surfaceindex;
11287         int triangleindex;
11288         int decalsurfaceindex;
11289         int cornerindex;
11290         int index;
11291         int numpoints;
11292         const int *e;
11293         float localorigin[3];
11294         float localnormal[3];
11295         float localmins[3];
11296         float localmaxs[3];
11297         float localsize;
11298         float ilocalsize;
11299         float v[9][3];
11300         float tc[9][2];
11301         float c[9][4];
11302         //float normal[3];
11303         float planes[6][4];
11304         float f;
11305         float points[2][9][3];
11306         float angles[3];
11307         float temp[3];
11308
11309         decalsystem = &ent->decalsystem;
11310         model = ent->model;
11311         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11312         {
11313                 R_DecalSystem_Reset(&ent->decalsystem);
11314                 return;
11315         }
11316
11317         if (!model->brush.data_nodes && !cl_decals_models.integer)
11318         {
11319                 if (decalsystem->model)
11320                         R_DecalSystem_Reset(decalsystem);
11321                 return;
11322         }
11323
11324         if (decalsystem->model != model)
11325                 R_DecalSystem_Reset(decalsystem);
11326         decalsystem->model = model;
11327
11328         RSurf_ActiveModelEntity(ent, false, false, false);
11329
11330         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11331         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11332         VectorNormalize(localnormal);
11333         localsize = worldsize*rsurface.inversematrixscale;
11334         ilocalsize = 1.0f / localsize;
11335         localmins[0] = localorigin[0] - localsize;
11336         localmins[1] = localorigin[1] - localsize;
11337         localmins[2] = localorigin[2] - localsize;
11338         localmaxs[0] = localorigin[0] + localsize;
11339         localmaxs[1] = localorigin[1] + localsize;
11340         localmaxs[2] = localorigin[2] + localsize;
11341
11342         //VectorCopy(localnormal, planes[4]);
11343         //VectorVectors(planes[4], planes[2], planes[0]);
11344         AnglesFromVectors(angles, localnormal, NULL, false);
11345         AngleVectors(angles, planes[0], planes[2], planes[4]);
11346         VectorNegate(planes[0], planes[1]);
11347         VectorNegate(planes[2], planes[3]);
11348         VectorNegate(planes[4], planes[5]);
11349         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11350         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11351         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11352         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11353         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11354         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11355
11356 #if 1
11357 // works
11358 {
11359         matrix4x4_t forwardprojection;
11360         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11361         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11362 }
11363 #else
11364 // broken
11365 {
11366         float projectionvector[4][3];
11367         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11368         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11369         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11370         projectionvector[0][0] = planes[0][0] * ilocalsize;
11371         projectionvector[0][1] = planes[1][0] * ilocalsize;
11372         projectionvector[0][2] = planes[2][0] * ilocalsize;
11373         projectionvector[1][0] = planes[0][1] * ilocalsize;
11374         projectionvector[1][1] = planes[1][1] * ilocalsize;
11375         projectionvector[1][2] = planes[2][1] * ilocalsize;
11376         projectionvector[2][0] = planes[0][2] * ilocalsize;
11377         projectionvector[2][1] = planes[1][2] * ilocalsize;
11378         projectionvector[2][2] = planes[2][2] * ilocalsize;
11379         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11380         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11381         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11382         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11383 }
11384 #endif
11385
11386         dynamic = model->surfmesh.isanimated;
11387         vertex3f = rsurface.modelvertex3f;
11388         numsurfacelist = model->nummodelsurfaces;
11389         surfacelist = model->sortedmodelsurfaces;
11390         surfaces = model->data_surfaces;
11391         for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11392         {
11393                 surfaceindex = surfacelist[surfacelistindex];
11394                 surface = surfaces + surfaceindex;
11395                 // check cull box first because it rejects more than any other check
11396                 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11397                         continue;
11398                 // skip transparent surfaces
11399                 texture = surface->texture;
11400                 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11401                         continue;
11402                 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11403                         continue;
11404                 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
11405                 numvertices = surface->num_vertices;
11406                 numtriangles = surface->num_triangles;
11407                 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
11408                 {
11409                         for (cornerindex = 0;cornerindex < 3;cornerindex++)
11410                         {
11411                                 index = 3*e[cornerindex];
11412                                 VectorCopy(vertex3f + index, v[cornerindex]);
11413                         }
11414                         // cull backfaces
11415                         //TriangleNormal(v[0], v[1], v[2], normal);
11416                         //if (DotProduct(normal, localnormal) < 0.0f)
11417                         //      continue;
11418                         // clip by each of the box planes formed from the projection matrix
11419                         // if anything survives, we emit the decal
11420                         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]);
11421                         if (numpoints < 3)
11422                                 continue;
11423                         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]);
11424                         if (numpoints < 3)
11425                                 continue;
11426                         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]);
11427                         if (numpoints < 3)
11428                                 continue;
11429                         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]);
11430                         if (numpoints < 3)
11431                                 continue;
11432                         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]);
11433                         if (numpoints < 3)
11434                                 continue;
11435                         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]);
11436                         if (numpoints < 3)
11437                                 continue;
11438                         // some part of the triangle survived, so we have to accept it...
11439                         if (dynamic)
11440                         {
11441                                 // dynamic always uses the original triangle
11442                                 numpoints = 3;
11443                                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11444                                 {
11445                                         index = 3*e[cornerindex];
11446                                         VectorCopy(vertex3f + index, v[cornerindex]);
11447                                 }
11448                         }
11449                         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11450                         {
11451                                 // convert vertex positions to texcoords
11452                                 Matrix4x4_Transform(&projection, v[cornerindex], temp);
11453                                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11454                                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11455                                 // calculate distance fade from the projection origin
11456                                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11457                                 f = bound(0.0f, f, 1.0f);
11458                                 c[cornerindex][0] = r * f;
11459                                 c[cornerindex][1] = g * f;
11460                                 c[cornerindex][2] = b * f;
11461                                 c[cornerindex][3] = 1.0f;
11462                                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11463                         }
11464                         if (dynamic)
11465                                 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);
11466                         else
11467                                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11468                                         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);
11469                 }
11470         }
11471 }
11472
11473 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11474 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)
11475 {
11476         int renderentityindex;
11477         float worldmins[3];
11478         float worldmaxs[3];
11479         entity_render_t *ent;
11480
11481         if (!cl_decals_newsystem.integer)
11482                 return;
11483
11484         worldmins[0] = worldorigin[0] - worldsize;
11485         worldmins[1] = worldorigin[1] - worldsize;
11486         worldmins[2] = worldorigin[2] - worldsize;
11487         worldmaxs[0] = worldorigin[0] + worldsize;
11488         worldmaxs[1] = worldorigin[1] + worldsize;
11489         worldmaxs[2] = worldorigin[2] + worldsize;
11490
11491         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11492
11493         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11494         {
11495                 ent = r_refdef.scene.entities[renderentityindex];
11496                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11497                         continue;
11498
11499                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11500         }
11501 }
11502
11503 typedef struct r_decalsystem_splatqueue_s
11504 {
11505         vec3_t worldorigin;
11506         vec3_t worldnormal;
11507         float color[4];
11508         float tcrange[4];
11509         float worldsize;
11510         int decalsequence;
11511 }
11512 r_decalsystem_splatqueue_t;
11513
11514 int r_decalsystem_numqueued = 0;
11515 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11516
11517 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)
11518 {
11519         r_decalsystem_splatqueue_t *queue;
11520
11521         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11522                 return;
11523
11524         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11525         VectorCopy(worldorigin, queue->worldorigin);
11526         VectorCopy(worldnormal, queue->worldnormal);
11527         Vector4Set(queue->color, r, g, b, a);
11528         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11529         queue->worldsize = worldsize;
11530         queue->decalsequence = cl.decalsequence++;
11531 }
11532
11533 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11534 {
11535         int i;
11536         r_decalsystem_splatqueue_t *queue;
11537
11538         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11539                 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);
11540         r_decalsystem_numqueued = 0;
11541 }
11542
11543 extern cvar_t cl_decals_max;
11544 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11545 {
11546         int i;
11547         decalsystem_t *decalsystem = &ent->decalsystem;
11548         int numdecals;
11549         int killsequence;
11550         tridecal_t *decal;
11551         float frametime;
11552         float lifetime;
11553
11554         if (!decalsystem->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         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11567         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11568
11569         if (decalsystem->lastupdatetime)
11570                 frametime = (cl.time - decalsystem->lastupdatetime);
11571         else
11572                 frametime = 0;
11573         decalsystem->lastupdatetime = cl.time;
11574         decal = decalsystem->decals;
11575         numdecals = decalsystem->numdecals;
11576
11577         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11578         {
11579                 if (decal->color4ub[0][3])
11580                 {
11581                         decal->lived += frametime;
11582                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11583                         {
11584                                 memset(decal, 0, sizeof(*decal));
11585                                 if (decalsystem->freedecal > i)
11586                                         decalsystem->freedecal = i;
11587                         }
11588                 }
11589         }
11590         decal = decalsystem->decals;
11591         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
11592                 numdecals--;
11593
11594         // collapse the array by shuffling the tail decals into the gaps
11595         for (;;)
11596         {
11597                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
11598                         decalsystem->freedecal++;
11599                 if (decalsystem->freedecal == numdecals)
11600                         break;
11601                 decal[decalsystem->freedecal] = decal[--numdecals];
11602         }
11603
11604         decalsystem->numdecals = numdecals;
11605
11606         if (numdecals <= 0)
11607         {
11608                 // if there are no decals left, reset decalsystem
11609                 R_DecalSystem_Reset(decalsystem);
11610         }
11611 }
11612
11613 extern skinframe_t *decalskinframe;
11614 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11615 {
11616         int i;
11617         decalsystem_t *decalsystem = &ent->decalsystem;
11618         int numdecals;
11619         tridecal_t *decal;
11620         float fadedelay;
11621         float faderate;
11622         float alpha;
11623         float *v3f;
11624         float *c4f;
11625         float *t2f;
11626         const int *e;
11627         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11628         int numtris = 0;
11629
11630         numdecals = decalsystem->numdecals;
11631         if (!numdecals)
11632                 return;
11633
11634         if (r_showsurfaces.integer)
11635                 return;
11636
11637         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11638         {
11639                 R_DecalSystem_Reset(decalsystem);
11640                 return;
11641         }
11642
11643         // if the model is static it doesn't matter what value we give for
11644         // wantnormals and wanttangents, so this logic uses only rules applicable
11645         // to a model, knowing that they are meaningless otherwise
11646         if (ent == r_refdef.scene.worldentity)
11647                 RSurf_ActiveWorldEntity();
11648         else
11649                 RSurf_ActiveModelEntity(ent, false, false, false);
11650
11651         decalsystem->lastupdatetime = cl.time;
11652         decal = decalsystem->decals;
11653
11654         fadedelay = cl_decals_time.value;
11655         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11656
11657         // update vertex positions for animated models
11658         v3f = decalsystem->vertex3f;
11659         c4f = decalsystem->color4f;
11660         t2f = decalsystem->texcoord2f;
11661         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11662         {
11663                 if (!decal->color4ub[0][3])
11664                         continue;
11665
11666                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11667                         continue;
11668
11669                 // update color values for fading decals
11670                 if (decal->lived >= cl_decals_time.value)
11671                 {
11672                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11673                         alpha *= (1.0f/255.0f);
11674                 }
11675                 else
11676                         alpha = 1.0f/255.0f;
11677
11678                 c4f[ 0] = decal->color4ub[0][0] * alpha;
11679                 c4f[ 1] = decal->color4ub[0][1] * alpha;
11680                 c4f[ 2] = decal->color4ub[0][2] * alpha;
11681                 c4f[ 3] = 1;
11682                 c4f[ 4] = decal->color4ub[1][0] * alpha;
11683                 c4f[ 5] = decal->color4ub[1][1] * alpha;
11684                 c4f[ 6] = decal->color4ub[1][2] * alpha;
11685                 c4f[ 7] = 1;
11686                 c4f[ 8] = decal->color4ub[2][0] * alpha;
11687                 c4f[ 9] = decal->color4ub[2][1] * alpha;
11688                 c4f[10] = decal->color4ub[2][2] * alpha;
11689                 c4f[11] = 1;
11690
11691                 t2f[0] = decal->texcoord2f[0][0];
11692                 t2f[1] = decal->texcoord2f[0][1];
11693                 t2f[2] = decal->texcoord2f[1][0];
11694                 t2f[3] = decal->texcoord2f[1][1];
11695                 t2f[4] = decal->texcoord2f[2][0];
11696                 t2f[5] = decal->texcoord2f[2][1];
11697
11698                 // update vertex positions for animated models
11699                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
11700                 {
11701                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11702                         VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
11703                         VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
11704                         VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
11705                 }
11706                 else
11707                 {
11708                         VectorCopy(decal->vertex3f[0], v3f);
11709                         VectorCopy(decal->vertex3f[1], v3f + 3);
11710                         VectorCopy(decal->vertex3f[2], v3f + 6);
11711                 }
11712
11713                 v3f += 9;
11714                 c4f += 12;
11715                 t2f += 6;
11716                 numtris++;
11717         }
11718
11719         if (numtris > 0)
11720         {
11721                 r_refdef.stats.drawndecals += numtris;
11722
11723                 if (r_refdef.fogenabled)
11724                 {
11725                         switch(vid.renderpath)
11726                         {
11727                         case RENDERPATH_GL20:
11728                         case RENDERPATH_CGGL:
11729                         case RENDERPATH_GL13:
11730                         case RENDERPATH_GL11:
11731                                 for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
11732                                 {
11733                                         alpha = RSurf_FogVertex(v3f);
11734                                         c4f[0] *= alpha;
11735                                         c4f[1] *= alpha;
11736                                         c4f[2] *= alpha;
11737                                 }
11738                                 break;
11739                         }
11740                 }
11741
11742                 // now render the decals all at once
11743                 // (this assumes they all use one particle font texture!)
11744                 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);
11745                 R_Mesh_ResetTextureState();
11746                 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
11747                 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
11748                 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
11749                 GL_DepthMask(false);
11750                 GL_DepthRange(0, 1);
11751                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11752                 GL_DepthTest(true);
11753                 GL_CullFace(GL_NONE);
11754                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11755                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
11756                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
11757         }
11758 }
11759
11760 static void R_DrawModelDecals(void)
11761 {
11762         int i, numdecals;
11763
11764         // fade faster when there are too many decals
11765         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11766         for (i = 0;i < r_refdef.scene.numentities;i++)
11767                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11768
11769         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11770         for (i = 0;i < r_refdef.scene.numentities;i++)
11771                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11772                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11773
11774         R_DecalSystem_ApplySplatEntitiesQueue();
11775
11776         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11777         for (i = 0;i < r_refdef.scene.numentities;i++)
11778                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11779
11780         r_refdef.stats.totaldecals += numdecals;
11781
11782         if (r_showsurfaces.integer)
11783                 return;
11784
11785         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11786
11787         for (i = 0;i < r_refdef.scene.numentities;i++)
11788         {
11789                 if (!r_refdef.viewcache.entityvisible[i])
11790                         continue;
11791                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11792                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11793         }
11794 }
11795
11796 void R_DrawDebugModel(void)
11797 {
11798         entity_render_t *ent = rsurface.entity;
11799         int i, j, k, l, flagsmask;
11800         const int *elements;
11801         q3mbrush_t *brush;
11802         const msurface_t *surface;
11803         dp_model_t *model = ent->model;
11804         vec3_t v;
11805
11806         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11807
11808         R_Mesh_ColorPointer(NULL, 0, 0);
11809         R_Mesh_ResetTextureState();
11810         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11811         GL_DepthRange(0, 1);
11812         GL_DepthTest(!r_showdisabledepthtest.integer);
11813         GL_DepthMask(false);
11814         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11815
11816         if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
11817         {
11818                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11819                 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
11820                 {
11821                         if (brush->colbrushf && brush->colbrushf->numtriangles)
11822                         {
11823                                 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
11824                                 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);
11825                                 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
11826                         }
11827                 }
11828                 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
11829                 {
11830                         if (surface->num_collisiontriangles)
11831                         {
11832                                 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
11833                                 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);
11834                                 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
11835                         }
11836                 }
11837         }
11838
11839         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11840
11841         if (r_showtris.integer || r_shownormals.integer)
11842         {
11843                 if (r_showdisabledepthtest.integer)
11844                 {
11845                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11846                         GL_DepthMask(false);
11847                 }
11848                 else
11849                 {
11850                         GL_BlendFunc(GL_ONE, GL_ZERO);
11851                         GL_DepthMask(true);
11852                 }
11853                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11854                 {
11855                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11856                                 continue;
11857                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11858                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11859                         {
11860                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
11861                                 if (r_showtris.value > 0)
11862                                 {
11863                                         if (!rsurface.texture->currentlayers->depthmask)
11864                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11865                                         else if (ent == r_refdef.scene.worldentity)
11866                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11867                                         else
11868                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11869                                         elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
11870                                         R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
11871                                         R_Mesh_ColorPointer(NULL, 0, 0);
11872                                         R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
11873                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11874                                         //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
11875                                         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);
11876                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11877                                         CHECKGLERROR
11878                                 }
11879                                 if (r_shownormals.value < 0)
11880                                 {
11881                                         qglBegin(GL_LINES);
11882                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11883                                         {
11884                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11885                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11886                                                 qglVertex3f(v[0], v[1], v[2]);
11887                                                 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
11888                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11889                                                 qglVertex3f(v[0], v[1], v[2]);
11890                                         }
11891                                         qglEnd();
11892                                         CHECKGLERROR
11893                                 }
11894                                 if (r_shownormals.value > 0)
11895                                 {
11896                                         qglBegin(GL_LINES);
11897                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11898                                         {
11899                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11900                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11901                                                 qglVertex3f(v[0], v[1], v[2]);
11902                                                 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
11903                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11904                                                 qglVertex3f(v[0], v[1], v[2]);
11905                                         }
11906                                         qglEnd();
11907                                         CHECKGLERROR
11908                                         qglBegin(GL_LINES);
11909                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11910                                         {
11911                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11912                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11913                                                 qglVertex3f(v[0], v[1], v[2]);
11914                                                 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
11915                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11916                                                 qglVertex3f(v[0], v[1], v[2]);
11917                                         }
11918                                         qglEnd();
11919                                         CHECKGLERROR
11920                                         qglBegin(GL_LINES);
11921                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11922                                         {
11923                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11924                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11925                                                 qglVertex3f(v[0], v[1], v[2]);
11926                                                 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
11927                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11928                                                 qglVertex3f(v[0], v[1], v[2]);
11929                                         }
11930                                         qglEnd();
11931                                         CHECKGLERROR
11932                                 }
11933                         }
11934                 }
11935                 rsurface.texture = NULL;
11936         }
11937 }
11938
11939 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11940 int r_maxsurfacelist = 0;
11941 const msurface_t **r_surfacelist = NULL;
11942 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11943 {
11944         int i, j, endj, f, flagsmask;
11945         texture_t *t;
11946         dp_model_t *model = r_refdef.scene.worldmodel;
11947         msurface_t *surfaces;
11948         unsigned char *update;
11949         int numsurfacelist = 0;
11950         if (model == NULL)
11951                 return;
11952
11953         if (r_maxsurfacelist < model->num_surfaces)
11954         {
11955                 r_maxsurfacelist = model->num_surfaces;
11956                 if (r_surfacelist)
11957                         Mem_Free((msurface_t**)r_surfacelist);
11958                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11959         }
11960
11961         RSurf_ActiveWorldEntity();
11962
11963         surfaces = model->data_surfaces;
11964         update = model->brushq1.lightmapupdateflags;
11965
11966         // update light styles on this submodel
11967         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11968         {
11969                 model_brush_lightstyleinfo_t *style;
11970                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11971                 {
11972                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11973                         {
11974                                 int *list = style->surfacelist;
11975                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11976                                 for (j = 0;j < style->numsurfaces;j++)
11977                                         update[list[j]] = true;
11978                         }
11979                 }
11980         }
11981
11982         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11983
11984         if (debug)
11985         {
11986                 R_DrawDebugModel();
11987                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11988                 return;
11989         }
11990
11991         f = 0;
11992         t = NULL;
11993         rsurface.uselightmaptexture = false;
11994         rsurface.texture = NULL;
11995         rsurface.rtlight = NULL;
11996         numsurfacelist = 0;
11997         // add visible surfaces to draw list
11998         for (i = 0;i < model->nummodelsurfaces;i++)
11999         {
12000                 j = model->sortedmodelsurfaces[i];
12001                 if (r_refdef.viewcache.world_surfacevisible[j])
12002                         r_surfacelist[numsurfacelist++] = surfaces + j;
12003         }
12004         // update lightmaps if needed
12005         if (model->brushq1.firstrender)
12006         {
12007                 model->brushq1.firstrender = false;
12008                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12009                         if (update[j])
12010                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12011         }
12012         else if (update)
12013         {
12014                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12015                         if (r_refdef.viewcache.world_surfacevisible[j])
12016                                 if (update[j])
12017                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12018         }
12019         // don't do anything if there were no surfaces
12020         if (!numsurfacelist)
12021         {
12022                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12023                 return;
12024         }
12025         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12026         GL_AlphaTest(false);
12027
12028         // add to stats if desired
12029         if (r_speeds.integer && !skysurfaces && !depthonly)
12030         {
12031                 r_refdef.stats.world_surfaces += numsurfacelist;
12032                 for (j = 0;j < numsurfacelist;j++)
12033                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
12034         }
12035
12036         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12037 }
12038
12039 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12040 {
12041         int i, j, endj, f, flagsmask;
12042         texture_t *t;
12043         dp_model_t *model = ent->model;
12044         msurface_t *surfaces;
12045         unsigned char *update;
12046         int numsurfacelist = 0;
12047         if (model == NULL)
12048                 return;
12049
12050         if (r_maxsurfacelist < model->num_surfaces)
12051         {
12052                 r_maxsurfacelist = model->num_surfaces;
12053                 if (r_surfacelist)
12054                         Mem_Free((msurface_t **)r_surfacelist);
12055                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12056         }
12057
12058         // if the model is static it doesn't matter what value we give for
12059         // wantnormals and wanttangents, so this logic uses only rules applicable
12060         // to a model, knowing that they are meaningless otherwise
12061         if (ent == r_refdef.scene.worldentity)
12062                 RSurf_ActiveWorldEntity();
12063         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12064                 RSurf_ActiveModelEntity(ent, false, false, false);
12065         else if (prepass)
12066                 RSurf_ActiveModelEntity(ent, true, true, true);
12067         else if (depthonly)
12068                 RSurf_ActiveModelEntity(ent, false, false, false);
12069         else
12070         {
12071                 switch (vid.renderpath)
12072                 {
12073                 case RENDERPATH_GL20:
12074                 case RENDERPATH_CGGL:
12075                         RSurf_ActiveModelEntity(ent, true, true, false);
12076                         break;
12077                 case RENDERPATH_GL13:
12078                 case RENDERPATH_GL11:
12079                         RSurf_ActiveModelEntity(ent, true, false, false);
12080                         break;
12081                 }
12082         }
12083
12084         surfaces = model->data_surfaces;
12085         update = model->brushq1.lightmapupdateflags;
12086
12087         // update light styles
12088         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12089         {
12090                 model_brush_lightstyleinfo_t *style;
12091                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12092                 {
12093                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12094                         {
12095                                 int *list = style->surfacelist;
12096                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12097                                 for (j = 0;j < style->numsurfaces;j++)
12098                                         update[list[j]] = true;
12099                         }
12100                 }
12101         }
12102
12103         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12104
12105         if (debug)
12106         {
12107                 R_DrawDebugModel();
12108                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12109                 return;
12110         }
12111
12112         f = 0;
12113         t = NULL;
12114         rsurface.uselightmaptexture = false;
12115         rsurface.texture = NULL;
12116         rsurface.rtlight = NULL;
12117         numsurfacelist = 0;
12118         // add visible surfaces to draw list
12119         for (i = 0;i < model->nummodelsurfaces;i++)
12120                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12121         // don't do anything if there were no surfaces
12122         if (!numsurfacelist)
12123         {
12124                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12125                 return;
12126         }
12127         // update lightmaps if needed
12128         if (update)
12129         {
12130                 int updated = 0;
12131                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12132                 {
12133                         if (update[j])
12134                         {
12135                                 updated++;
12136                                 R_BuildLightMap(ent, surfaces + j);
12137                         }
12138                 }
12139         }
12140         if (update)
12141                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12142                         if (update[j])
12143                                 R_BuildLightMap(ent, surfaces + j);
12144         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12145         GL_AlphaTest(false);
12146
12147         // add to stats if desired
12148         if (r_speeds.integer && !skysurfaces && !depthonly)
12149         {
12150                 r_refdef.stats.entities_surfaces += numsurfacelist;
12151                 for (j = 0;j < numsurfacelist;j++)
12152                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
12153         }
12154
12155         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12156 }
12157
12158 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12159 {
12160         static texture_t texture;
12161         static msurface_t surface;
12162         const msurface_t *surfacelist = &surface;
12163
12164         // fake enough texture and surface state to render this geometry
12165
12166         texture.update_lastrenderframe = -1; // regenerate this texture
12167         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12168         texture.currentskinframe = skinframe;
12169         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12170         texture.specularscalemod = 1;
12171         texture.specularpowermod = 1;
12172
12173         surface.texture = &texture;
12174         surface.num_triangles = numtriangles;
12175         surface.num_firsttriangle = firsttriangle;
12176         surface.num_vertices = numvertices;
12177         surface.num_firstvertex = firstvertex;
12178
12179         // now render it
12180         rsurface.texture = R_GetCurrentTexture(surface.texture);
12181         rsurface.uselightmaptexture = false;
12182         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12183 }
12184
12185 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)
12186 {
12187         static msurface_t surface;
12188         const msurface_t *surfacelist = &surface;
12189
12190         // fake enough texture and surface state to render this geometry
12191
12192         surface.texture = texture;
12193         surface.num_triangles = numtriangles;
12194         surface.num_firsttriangle = firsttriangle;
12195         surface.num_vertices = numvertices;
12196         surface.num_firstvertex = firstvertex;
12197
12198         // now render it
12199         rsurface.texture = R_GetCurrentTexture(surface.texture);
12200         rsurface.uselightmaptexture = false;
12201         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12202 }