]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
make sure r_glsl_permutation and r_cg_permutation variables are NULL
[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_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
95 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
96 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
97 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"};
98 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"};
99 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
100 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
101 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
102 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
103 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"};
104
105 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
106 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
107 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
108 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
109 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
110 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
111 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
112 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
113
114 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)"};
115 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"};
116
117 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
118 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
119 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
120 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
121 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
122
123 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
124 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
125 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
126
127 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)"};
128 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
129 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
130 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
131 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
132 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)"};
133 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)"};
134 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)"};
135 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)"};
136
137 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)"};
138 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
139 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"};
140 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
141 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
142
143 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
144 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
145 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
146 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
147
148 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
149 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
150 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
151 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
152 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
153 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
154 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
155
156 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
157 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
158 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
159 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)"};
160
161 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"};
162
163 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"};
164
165 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
166
167 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
168 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
169 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"};
170 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
171 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
172 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
173 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
174 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)"};
175
176 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
177
178 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)"};
179
180 extern cvar_t v_glslgamma;
181
182 extern qboolean v_flipped_state;
183
184 static struct r_bloomstate_s
185 {
186         qboolean enabled;
187         qboolean hdr;
188
189         int bloomwidth, bloomheight;
190
191         int screentexturewidth, screentextureheight;
192         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
193
194         int bloomtexturewidth, bloomtextureheight;
195         rtexture_t *texture_bloom;
196
197         // arrays for rendering the screen passes
198         float screentexcoord2f[8];
199         float bloomtexcoord2f[8];
200         float offsettexcoord2f[8];
201
202         r_viewport_t viewport;
203 }
204 r_bloomstate;
205
206 r_waterstate_t r_waterstate;
207
208 /// shadow volume bsp struct with automatically growing nodes buffer
209 svbsp_t r_svbsp;
210
211 rtexture_t *r_texture_blanknormalmap;
212 rtexture_t *r_texture_white;
213 rtexture_t *r_texture_grey128;
214 rtexture_t *r_texture_black;
215 rtexture_t *r_texture_notexture;
216 rtexture_t *r_texture_whitecube;
217 rtexture_t *r_texture_normalizationcube;
218 rtexture_t *r_texture_fogattenuation;
219 rtexture_t *r_texture_gammaramps;
220 unsigned int r_texture_gammaramps_serial;
221 //rtexture_t *r_texture_fogintensity;
222 rtexture_t *r_texture_reflectcube;
223
224 // TODO: hash lookups?
225 typedef struct cubemapinfo_s
226 {
227         char basename[64];
228         rtexture_t *texture;
229 }
230 cubemapinfo_t;
231
232 int r_texture_numcubemaps;
233 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
234
235 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
236 unsigned int r_numqueries;
237 unsigned int r_maxqueries;
238
239 typedef struct r_qwskincache_s
240 {
241         char name[MAX_QPATH];
242         skinframe_t *skinframe;
243 }
244 r_qwskincache_t;
245
246 static r_qwskincache_t *r_qwskincache;
247 static int r_qwskincache_size;
248
249 /// vertex coordinates for a quad that covers the screen exactly
250 const float r_screenvertex3f[12] =
251 {
252         0, 0, 0,
253         1, 0, 0,
254         1, 1, 0,
255         0, 1, 0
256 };
257
258 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
259 {
260         int i;
261         for (i = 0;i < verts;i++)
262         {
263                 out[0] = in[0] * r;
264                 out[1] = in[1] * g;
265                 out[2] = in[2] * b;
266                 out[3] = in[3];
267                 in += 4;
268                 out += 4;
269         }
270 }
271
272 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
273 {
274         int i;
275         for (i = 0;i < verts;i++)
276         {
277                 out[0] = r;
278                 out[1] = g;
279                 out[2] = b;
280                 out[3] = a;
281                 out += 4;
282         }
283 }
284
285 // FIXME: move this to client?
286 void FOG_clear(void)
287 {
288         if (gamemode == GAME_NEHAHRA)
289         {
290                 Cvar_Set("gl_fogenable", "0");
291                 Cvar_Set("gl_fogdensity", "0.2");
292                 Cvar_Set("gl_fogred", "0.3");
293                 Cvar_Set("gl_foggreen", "0.3");
294                 Cvar_Set("gl_fogblue", "0.3");
295         }
296         r_refdef.fog_density = 0;
297         r_refdef.fog_red = 0;
298         r_refdef.fog_green = 0;
299         r_refdef.fog_blue = 0;
300         r_refdef.fog_alpha = 1;
301         r_refdef.fog_start = 0;
302         r_refdef.fog_end = 16384;
303         r_refdef.fog_height = 1<<30;
304         r_refdef.fog_fadedepth = 128;
305 }
306
307 static void R_BuildBlankTextures(void)
308 {
309         unsigned char data[4];
310         data[2] = 128; // normal X
311         data[1] = 128; // normal Y
312         data[0] = 255; // normal Z
313         data[3] = 128; // height
314         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
315         data[0] = 255;
316         data[1] = 255;
317         data[2] = 255;
318         data[3] = 255;
319         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
320         data[0] = 128;
321         data[1] = 128;
322         data[2] = 128;
323         data[3] = 255;
324         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
325         data[0] = 0;
326         data[1] = 0;
327         data[2] = 0;
328         data[3] = 255;
329         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
330 }
331
332 static void R_BuildNoTexture(void)
333 {
334         int x, y;
335         unsigned char pix[16][16][4];
336         // this makes a light grey/dark grey checkerboard texture
337         for (y = 0;y < 16;y++)
338         {
339                 for (x = 0;x < 16;x++)
340                 {
341                         if ((y < 8) ^ (x < 8))
342                         {
343                                 pix[y][x][0] = 128;
344                                 pix[y][x][1] = 128;
345                                 pix[y][x][2] = 128;
346                                 pix[y][x][3] = 255;
347                         }
348                         else
349                         {
350                                 pix[y][x][0] = 64;
351                                 pix[y][x][1] = 64;
352                                 pix[y][x][2] = 64;
353                                 pix[y][x][3] = 255;
354                         }
355                 }
356         }
357         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
358 }
359
360 static void R_BuildWhiteCube(void)
361 {
362         unsigned char data[6*1*1*4];
363         memset(data, 255, sizeof(data));
364         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
365 }
366
367 static void R_BuildNormalizationCube(void)
368 {
369         int x, y, side;
370         vec3_t v;
371         vec_t s, t, intensity;
372 #define NORMSIZE 64
373         unsigned char *data;
374         data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
375         for (side = 0;side < 6;side++)
376         {
377                 for (y = 0;y < NORMSIZE;y++)
378                 {
379                         for (x = 0;x < NORMSIZE;x++)
380                         {
381                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
382                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
383                                 switch(side)
384                                 {
385                                 default:
386                                 case 0:
387                                         v[0] = 1;
388                                         v[1] = -t;
389                                         v[2] = -s;
390                                         break;
391                                 case 1:
392                                         v[0] = -1;
393                                         v[1] = -t;
394                                         v[2] = s;
395                                         break;
396                                 case 2:
397                                         v[0] = s;
398                                         v[1] = 1;
399                                         v[2] = t;
400                                         break;
401                                 case 3:
402                                         v[0] = s;
403                                         v[1] = -1;
404                                         v[2] = -t;
405                                         break;
406                                 case 4:
407                                         v[0] = s;
408                                         v[1] = -t;
409                                         v[2] = 1;
410                                         break;
411                                 case 5:
412                                         v[0] = -s;
413                                         v[1] = -t;
414                                         v[2] = -1;
415                                         break;
416                                 }
417                                 intensity = 127.0f / sqrt(DotProduct(v, v));
418                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
419                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
420                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
421                                 data[((side*64+y)*64+x)*4+3] = 255;
422                         }
423                 }
424         }
425         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
426         Mem_Free(data);
427 }
428
429 static void R_BuildFogTexture(void)
430 {
431         int x, b;
432 #define FOGWIDTH 256
433         unsigned char data1[FOGWIDTH][4];
434         //unsigned char data2[FOGWIDTH][4];
435         double d, r, alpha;
436
437         r_refdef.fogmasktable_start = r_refdef.fog_start;
438         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
439         r_refdef.fogmasktable_range = r_refdef.fogrange;
440         r_refdef.fogmasktable_density = r_refdef.fog_density;
441
442         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
443         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
444         {
445                 d = (x * r - r_refdef.fogmasktable_start);
446                 if(developer_extra.integer)
447                         Con_DPrintf("%f ", d);
448                 d = max(0, d);
449                 if (r_fog_exp2.integer)
450                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
451                 else
452                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
453                 if(developer_extra.integer)
454                         Con_DPrintf(" : %f ", alpha);
455                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
456                 if(developer_extra.integer)
457                         Con_DPrintf(" = %f\n", alpha);
458                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
459         }
460
461         for (x = 0;x < FOGWIDTH;x++)
462         {
463                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
464                 data1[x][0] = b;
465                 data1[x][1] = b;
466                 data1[x][2] = b;
467                 data1[x][3] = 255;
468                 //data2[x][0] = 255 - b;
469                 //data2[x][1] = 255 - b;
470                 //data2[x][2] = 255 - b;
471                 //data2[x][3] = 255;
472         }
473         if (r_texture_fogattenuation)
474         {
475                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
476                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
477         }
478         else
479         {
480                 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);
481                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
482         }
483 }
484
485 //=======================================================================================================================================================
486
487 static const char *builtinshaderstring =
488 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
489 "// written by Forest 'LordHavoc' Hale\n"
490 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
491 "\n"
492 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
493 "# define USEFOG\n"
494 "#endif\n"
495 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
496 "#define USELIGHTMAP\n"
497 "#endif\n"
498 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
499 "#define USEEYEVECTOR\n"
500 "#endif\n"
501 "\n"
502 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
503 "# extension GL_ARB_texture_rectangle : enable\n"
504 "#endif\n"
505 "\n"
506 "#ifdef USESHADOWMAP2D\n"
507 "# ifdef GL_EXT_gpu_shader4\n"
508 "#   extension GL_EXT_gpu_shader4 : enable\n"
509 "# endif\n"
510 "# ifdef GL_ARB_texture_gather\n"
511 "#   extension GL_ARB_texture_gather : enable\n"
512 "# else\n"
513 "#   ifdef GL_AMD_texture_texture4\n"
514 "#     extension GL_AMD_texture_texture4 : enable\n"
515 "#   endif\n"
516 "# endif\n"
517 "#endif\n"
518 "\n"
519 "#ifdef USESHADOWMAPCUBE\n"
520 "# extension GL_EXT_gpu_shader4 : enable\n"
521 "#endif\n"
522 "\n"
523 "//#ifdef USESHADOWSAMPLER\n"
524 "//# extension GL_ARB_shadow : enable\n"
525 "//#endif\n"
526 "\n"
527 "//#ifdef __GLSL_CG_DATA_TYPES\n"
528 "//# define myhalf half\n"
529 "//# define myhalf2 half2\n"
530 "//# define myhalf3 half3\n"
531 "//# define myhalf4 half4\n"
532 "//#else\n"
533 "# define myhalf float\n"
534 "# define myhalf2 vec2\n"
535 "# define myhalf3 vec3\n"
536 "# define myhalf4 vec4\n"
537 "//#endif\n"
538 "\n"
539 "#ifdef VERTEX_SHADER\n"
540 "uniform mat4 ModelViewProjectionMatrix;\n"
541 "#endif\n"
542 "\n"
543 "#ifdef MODE_DEPTH_OR_SHADOW\n"
544 "#ifdef VERTEX_SHADER\n"
545 "void main(void)\n"
546 "{\n"
547 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
548 "}\n"
549 "#endif\n"
550 "#else // !MODE_DEPTH_ORSHADOW\n"
551 "\n"
552 "\n"
553 "\n"
554 "\n"
555 "#ifdef MODE_SHOWDEPTH\n"
556 "#ifdef VERTEX_SHADER\n"
557 "void main(void)\n"
558 "{\n"
559 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
560 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
561 "}\n"
562 "#endif\n"
563 "\n"
564 "#ifdef FRAGMENT_SHADER\n"
565 "void main(void)\n"
566 "{\n"
567 "       gl_FragColor = gl_Color;\n"
568 "}\n"
569 "#endif\n"
570 "#else // !MODE_SHOWDEPTH\n"
571 "\n"
572 "\n"
573 "\n"
574 "\n"
575 "#ifdef MODE_POSTPROCESS\n"
576 "varying vec2 TexCoord1;\n"
577 "varying vec2 TexCoord2;\n"
578 "\n"
579 "#ifdef VERTEX_SHADER\n"
580 "void main(void)\n"
581 "{\n"
582 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
583 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
584 "#ifdef USEBLOOM\n"
585 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
586 "#endif\n"
587 "}\n"
588 "#endif\n"
589 "\n"
590 "#ifdef FRAGMENT_SHADER\n"
591 "uniform sampler2D Texture_First;\n"
592 "#ifdef USEBLOOM\n"
593 "uniform sampler2D Texture_Second;\n"
594 "#endif\n"
595 "#ifdef USEGAMMARAMPS\n"
596 "uniform sampler2D Texture_GammaRamps;\n"
597 "#endif\n"
598 "#ifdef USESATURATION\n"
599 "uniform float Saturation;\n"
600 "#endif\n"
601 "#ifdef USEVIEWTINT\n"
602 "uniform vec4 ViewTintColor;\n"
603 "#endif\n"
604 "//uncomment these if you want to use them:\n"
605 "uniform vec4 UserVec1;\n"
606 "// uniform vec4 UserVec2;\n"
607 "// uniform vec4 UserVec3;\n"
608 "// uniform vec4 UserVec4;\n"
609 "// uniform float ClientTime;\n"
610 "uniform vec2 PixelSize;\n"
611 "void main(void)\n"
612 "{\n"
613 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
614 "#ifdef USEBLOOM\n"
615 "       gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
616 "#endif\n"
617 "#ifdef USEVIEWTINT\n"
618 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
619 "#endif\n"
620 "\n"
621 "#ifdef USEPOSTPROCESSING\n"
622 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
623 "// 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"
624 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
625 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
626 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
627 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
628 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
629 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
630 "#endif\n"
631 "\n"
632 "#ifdef USESATURATION\n"
633 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
634 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
635 "       //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
636 "       gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
637 "#endif\n"
638 "\n"
639 "#ifdef USEGAMMARAMPS\n"
640 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
641 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
642 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
643 "#endif\n"
644 "}\n"
645 "#endif\n"
646 "#else // !MODE_POSTPROCESS\n"
647 "\n"
648 "\n"
649 "\n"
650 "\n"
651 "#ifdef MODE_GENERIC\n"
652 "#ifdef USEDIFFUSE\n"
653 "varying vec2 TexCoord1;\n"
654 "#endif\n"
655 "#ifdef USESPECULAR\n"
656 "varying vec2 TexCoord2;\n"
657 "#endif\n"
658 "#ifdef VERTEX_SHADER\n"
659 "void main(void)\n"
660 "{\n"
661 "       gl_FrontColor = gl_Color;\n"
662 "#ifdef USEDIFFUSE\n"
663 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
664 "#endif\n"
665 "#ifdef USESPECULAR\n"
666 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
667 "#endif\n"
668 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
669 "}\n"
670 "#endif\n"
671 "\n"
672 "#ifdef FRAGMENT_SHADER\n"
673 "#ifdef USEDIFFUSE\n"
674 "uniform sampler2D Texture_First;\n"
675 "#endif\n"
676 "#ifdef USESPECULAR\n"
677 "uniform sampler2D Texture_Second;\n"
678 "#endif\n"
679 "\n"
680 "void main(void)\n"
681 "{\n"
682 "       gl_FragColor = gl_Color;\n"
683 "#ifdef USEDIFFUSE\n"
684 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
685 "#endif\n"
686 "\n"
687 "#ifdef USESPECULAR\n"
688 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
689 "# ifdef USECOLORMAPPING\n"
690 "       gl_FragColor *= tex2;\n"
691 "# endif\n"
692 "# ifdef USEGLOW\n"
693 "       gl_FragColor += tex2;\n"
694 "# endif\n"
695 "# ifdef USEVERTEXTEXTUREBLEND\n"
696 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
697 "# endif\n"
698 "#endif\n"
699 "}\n"
700 "#endif\n"
701 "#else // !MODE_GENERIC\n"
702 "\n"
703 "\n"
704 "\n"
705 "\n"
706 "#ifdef MODE_BLOOMBLUR\n"
707 "varying TexCoord;\n"
708 "#ifdef VERTEX_SHADER\n"
709 "void main(void)\n"
710 "{\n"
711 "       gl_FrontColor = gl_Color;\n"
712 "       TexCoord = gl_MultiTexCoord0.xy;\n"
713 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
714 "}\n"
715 "#endif\n"
716 "\n"
717 "#ifdef FRAGMENT_SHADER\n"
718 "uniform sampler2D Texture_First;\n"
719 "uniform vec4 BloomBlur_Parameters;\n"
720 "\n"
721 "void main(void)\n"
722 "{\n"
723 "       int i;\n"
724 "       vec2 tc = TexCoord;\n"
725 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
726 "       tc += BloomBlur_Parameters.xy;\n"
727 "       for (i = 1;i < SAMPLES;i++)\n"
728 "       {\n"
729 "               color += texture2D(Texture_First, tc).rgb;\n"
730 "               tc += BloomBlur_Parameters.xy;\n"
731 "       }\n"
732 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
733 "}\n"
734 "#endif\n"
735 "#else // !MODE_BLOOMBLUR\n"
736 "#ifdef MODE_REFRACTION\n"
737 "varying vec2 TexCoord;\n"
738 "varying vec4 ModelViewProjectionPosition;\n"
739 "uniform mat4 TexMatrix;\n"
740 "#ifdef VERTEX_SHADER\n"
741 "\n"
742 "void main(void)\n"
743 "{\n"
744 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
745 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
746 "       ModelViewProjectionPosition = gl_Position;\n"
747 "}\n"
748 "#endif\n"
749 "\n"
750 "#ifdef FRAGMENT_SHADER\n"
751 "uniform sampler2D Texture_Normal;\n"
752 "uniform sampler2D Texture_Refraction;\n"
753 "uniform sampler2D Texture_Reflection;\n"
754 "\n"
755 "uniform vec4 DistortScaleRefractReflect;\n"
756 "uniform vec4 ScreenScaleRefractReflect;\n"
757 "uniform vec4 ScreenCenterRefractReflect;\n"
758 "uniform vec4 RefractColor;\n"
759 "uniform vec4 ReflectColor;\n"
760 "uniform float ReflectFactor;\n"
761 "uniform float ReflectOffset;\n"
762 "\n"
763 "void main(void)\n"
764 "{\n"
765 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
766 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
767 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
768 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
769 "       // FIXME temporary hack to detect the case that the reflection\n"
770 "       // gets blackened at edges due to leaving the area that contains actual\n"
771 "       // content.\n"
772 "       // Remove this 'ack once we have a better way to stop this thing from\n"
773 "       // 'appening.\n"
774 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
775 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
776 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
777 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
778 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
779 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
780 "}\n"
781 "#endif\n"
782 "#else // !MODE_REFRACTION\n"
783 "\n"
784 "\n"
785 "\n"
786 "\n"
787 "#ifdef MODE_WATER\n"
788 "varying vec2 TexCoord;\n"
789 "varying vec3 EyeVector;\n"
790 "varying vec4 ModelViewProjectionPosition;\n"
791 "#ifdef VERTEX_SHADER\n"
792 "uniform vec3 EyePosition;\n"
793 "uniform mat4 TexMatrix;\n"
794 "\n"
795 "void main(void)\n"
796 "{\n"
797 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
798 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
799 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
800 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
801 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
802 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
803 "       ModelViewProjectionPosition = gl_Position;\n"
804 "}\n"
805 "#endif\n"
806 "\n"
807 "#ifdef FRAGMENT_SHADER\n"
808 "uniform sampler2D Texture_Normal;\n"
809 "uniform sampler2D Texture_Refraction;\n"
810 "uniform sampler2D Texture_Reflection;\n"
811 "\n"
812 "uniform vec4 DistortScaleRefractReflect;\n"
813 "uniform vec4 ScreenScaleRefractReflect;\n"
814 "uniform vec4 ScreenCenterRefractReflect;\n"
815 "uniform vec4 RefractColor;\n"
816 "uniform vec4 ReflectColor;\n"
817 "uniform float ReflectFactor;\n"
818 "uniform float ReflectOffset;\n"
819 "\n"
820 "void main(void)\n"
821 "{\n"
822 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
823 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
824 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
825 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
826 "       vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
827 "       // FIXME temporary hack to detect the case that the reflection\n"
828 "       // gets blackened at edges due to leaving the area that contains actual\n"
829 "       // content.\n"
830 "       // Remove this 'ack once we have a better way to stop this thing from\n"
831 "       // 'appening.\n"
832 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
833 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
834 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
835 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
836 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
837 "       f       = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
838 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
839 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
840 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
841 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
842 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
843 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
844 "}\n"
845 "#endif\n"
846 "#else // !MODE_WATER\n"
847 "\n"
848 "\n"
849 "\n"
850 "\n"
851 "// common definitions between vertex shader and fragment shader:\n"
852 "\n"
853 "varying vec2 TexCoord;\n"
854 "#ifdef USEVERTEXTEXTUREBLEND\n"
855 "varying vec2 TexCoord2;\n"
856 "#endif\n"
857 "#ifdef USELIGHTMAP\n"
858 "varying vec2 TexCoordLightmap;\n"
859 "#endif\n"
860 "\n"
861 "#ifdef MODE_LIGHTSOURCE\n"
862 "varying vec3 CubeVector;\n"
863 "#endif\n"
864 "\n"
865 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
866 "varying vec3 LightVector;\n"
867 "#endif\n"
868 "\n"
869 "#ifdef USEEYEVECTOR\n"
870 "varying vec3 EyeVector;\n"
871 "#endif\n"
872 "#ifdef USEFOG\n"
873 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
874 "#endif\n"
875 "\n"
876 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
877 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
878 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
879 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
880 "#endif\n"
881 "\n"
882 "#ifdef USEREFLECTION\n"
883 "varying vec4 ModelViewProjectionPosition;\n"
884 "#endif\n"
885 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
886 "uniform vec3 LightPosition;\n"
887 "varying vec4 ModelViewPosition;\n"
888 "#endif\n"
889 "\n"
890 "#ifdef MODE_LIGHTSOURCE\n"
891 "uniform vec3 LightPosition;\n"
892 "#endif\n"
893 "uniform vec3 EyePosition;\n"
894 "#ifdef MODE_LIGHTDIRECTION\n"
895 "uniform vec3 LightDir;\n"
896 "#endif\n"
897 "uniform vec4 FogPlane;\n"
898 "\n"
899 "#ifdef USESHADOWMAPORTHO\n"
900 "varying vec3 ShadowMapTC;\n"
901 "#endif\n"
902 "\n"
903 "\n"
904 "\n"
905 "\n"
906 "\n"
907 "// 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"
908 "\n"
909 "// fragment shader specific:\n"
910 "#ifdef FRAGMENT_SHADER\n"
911 "\n"
912 "uniform sampler2D Texture_Normal;\n"
913 "uniform sampler2D Texture_Color;\n"
914 "uniform sampler2D Texture_Gloss;\n"
915 "#ifdef USEGLOW\n"
916 "uniform sampler2D Texture_Glow;\n"
917 "#endif\n"
918 "#ifdef USEVERTEXTEXTUREBLEND\n"
919 "uniform sampler2D Texture_SecondaryNormal;\n"
920 "uniform sampler2D Texture_SecondaryColor;\n"
921 "uniform sampler2D Texture_SecondaryGloss;\n"
922 "#ifdef USEGLOW\n"
923 "uniform sampler2D Texture_SecondaryGlow;\n"
924 "#endif\n"
925 "#endif\n"
926 "#ifdef USECOLORMAPPING\n"
927 "uniform sampler2D Texture_Pants;\n"
928 "uniform sampler2D Texture_Shirt;\n"
929 "#endif\n"
930 "#ifdef USEFOG\n"
931 "uniform sampler2D Texture_FogMask;\n"
932 "#endif\n"
933 "#ifdef USELIGHTMAP\n"
934 "uniform sampler2D Texture_Lightmap;\n"
935 "#endif\n"
936 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
937 "uniform sampler2D Texture_Deluxemap;\n"
938 "#endif\n"
939 "#ifdef USEREFLECTION\n"
940 "uniform sampler2D Texture_Reflection;\n"
941 "#endif\n"
942 "\n"
943 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
944 "uniform sampler2D Texture_ScreenDepth;\n"
945 "uniform sampler2D Texture_ScreenNormalMap;\n"
946 "#endif\n"
947 "#ifdef USEDEFERREDLIGHTMAP\n"
948 "uniform sampler2D Texture_ScreenDiffuse;\n"
949 "uniform sampler2D Texture_ScreenSpecular;\n"
950 "#endif\n"
951 "\n"
952 "uniform myhalf3 Color_Pants;\n"
953 "uniform myhalf3 Color_Shirt;\n"
954 "uniform myhalf3 FogColor;\n"
955 "\n"
956 "#ifdef USEFOG\n"
957 "uniform float FogRangeRecip;\n"
958 "uniform float FogPlaneViewDist;\n"
959 "uniform float FogHeightFade;\n"
960 "float FogVertex(void)\n"
961 "{\n"
962 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
963 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
964 "       float fogfrac;\n"
965 "#ifdef USEFOGOUTSIDE\n"
966 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
967 "#else\n"
968 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
969 "#endif\n"
970 "       return float(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
971 "}\n"
972 "#endif\n"
973 "\n"
974 "#ifdef USEOFFSETMAPPING\n"
975 "uniform float OffsetMapping_Scale;\n"
976 "vec2 OffsetMapping(vec2 TexCoord)\n"
977 "{\n"
978 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
979 "       // 14 sample relief mapping: linear search and then binary search\n"
980 "       // this basically steps forward a small amount repeatedly until it finds\n"
981 "       // itself inside solid, then jitters forward and back using decreasing\n"
982 "       // amounts to find the impact\n"
983 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
984 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
985 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
986 "       vec3 RT = vec3(TexCoord, 1);\n"
987 "       OffsetVector *= 0.1;\n"
988 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
989 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
990 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
991 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
992 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
993 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
994 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
995 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
996 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
997 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
998 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
999 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1000 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1001 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1002 "       return RT.xy;\n"
1003 "#else\n"
1004 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1005 "       // this basically moves forward the full distance, and then backs up based\n"
1006 "       // on height of samples\n"
1007 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1008 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1009 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1010 "       TexCoord += OffsetVector;\n"
1011 "       OffsetVector *= 0.333;\n"
1012 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1013 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1014 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1015 "       return TexCoord;\n"
1016 "#endif\n"
1017 "}\n"
1018 "#endif // USEOFFSETMAPPING\n"
1019 "\n"
1020 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1021 "uniform sampler2D Texture_Attenuation;\n"
1022 "uniform samplerCube Texture_Cube;\n"
1023 "#endif\n"
1024 "\n"
1025 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1026 "\n"
1027 "#ifdef USESHADOWMAPRECT\n"
1028 "# ifdef USESHADOWSAMPLER\n"
1029 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1030 "# else\n"
1031 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1032 "# endif\n"
1033 "#endif\n"
1034 "\n"
1035 "#ifdef USESHADOWMAP2D\n"
1036 "# ifdef USESHADOWSAMPLER\n"
1037 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1038 "# else\n"
1039 "uniform sampler2D Texture_ShadowMap2D;\n"
1040 "# endif\n"
1041 "#endif\n"
1042 "\n"
1043 "#ifdef USESHADOWMAPVSDCT\n"
1044 "uniform samplerCube Texture_CubeProjection;\n"
1045 "#endif\n"
1046 "\n"
1047 "#ifdef USESHADOWMAPCUBE\n"
1048 "# ifdef USESHADOWSAMPLER\n"
1049 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1050 "# else\n"
1051 "uniform samplerCube Texture_ShadowMapCube;\n"
1052 "# endif\n"
1053 "#endif\n"
1054 "\n"
1055 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1056 "uniform vec2 ShadowMap_TextureScale;\n"
1057 "uniform vec4 ShadowMap_Parameters;\n"
1058 "#endif\n"
1059 "\n"
1060 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1061 "# ifdef USESHADOWMAPORTHO\n"
1062 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1063 "# else\n"
1064 "#  ifdef USESHADOWMAPVSDCT\n"
1065 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1066 "{\n"
1067 "       vec3 adir = abs(dir);\n"
1068 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1069 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1070 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1071 "}\n"
1072 "#  else\n"
1073 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1074 "{\n"
1075 "       vec3 adir = abs(dir);\n"
1076 "       float ma = adir.z;\n"
1077 "       vec4 proj = vec4(dir, 2.5);\n"
1078 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1079 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1080 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1081 "       return vec3(proj.xy * aparams.x + vec2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1082 "}\n"
1083 "#  endif\n"
1084 "# endif\n"
1085 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1086 "\n"
1087 "#ifdef USESHADOWMAPCUBE\n"
1088 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1089 "{\n"
1090 "       vec3 adir = abs(dir);\n"
1091 "       return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1092 "}\n"
1093 "#endif\n"
1094 "\n"
1095 "# ifdef USESHADOWMAPRECT\n"
1096 "float ShadowMapCompare(vec3 dir)\n"
1097 "{\n"
1098 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1099 "       float f;\n"
1100 "#  ifdef USESHADOWSAMPLER\n"
1101 "\n"
1102 "#    ifdef USESHADOWMAPPCF\n"
1103 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1104 "       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"
1105 "#    else\n"
1106 "       f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1107 "#    endif\n"
1108 "\n"
1109 "#  else\n"
1110 "\n"
1111 "#    ifdef USESHADOWMAPPCF\n"
1112 "#      if USESHADOWMAPPCF > 1\n"
1113 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1114 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1115 "       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"
1116 "       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"
1117 "       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"
1118 "       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"
1119 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1120 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1121 "#      else\n"
1122 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1123 "       vec2 offset = fract(shadowmaptc.xy);\n"
1124 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1125 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1126 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1127 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1128 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1129 "#      endif\n"
1130 "#    else\n"
1131 "       f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1132 "#    endif\n"
1133 "\n"
1134 "#  endif\n"
1135 "#  ifdef USESHADOWMAPORTHO\n"
1136 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1137 "#  else\n"
1138 "       return f;\n"
1139 "#  endif\n"
1140 "}\n"
1141 "# endif\n"
1142 "\n"
1143 "# ifdef USESHADOWMAP2D\n"
1144 "float ShadowMapCompare(vec3 dir)\n"
1145 "{\n"
1146 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1147 "       float f;\n"
1148 "\n"
1149 "#  ifdef USESHADOWSAMPLER\n"
1150 "#    ifdef USESHADOWMAPPCF\n"
1151 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1152 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1153 "       f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1154 "#    else\n"
1155 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1156 "#    endif\n"
1157 "#  else\n"
1158 "#    ifdef USESHADOWMAPPCF\n"
1159 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1160 "#      ifdef GL_ARB_texture_gather\n"
1161 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1162 "#      else\n"
1163 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1164 "#      endif\n"
1165 "       vec2 center = shadowmaptc.xy - 1.5, offset = fract(center);\n"
1166 "       center = (center - offset)*ShadowMap_TextureScale;\n"
1167 "       vec4 group1 = step(shadowmaptc.z, texval(0.0, 0.0));\n"
1168 "       vec4 group2 = step(shadowmaptc.z, texval(2.0, 0.0));\n"
1169 "       vec4 group3 = step(shadowmaptc.z, texval(0.0, 2.0));\n"
1170 "       vec4 group4 = step(shadowmaptc.z, texval(2.0, 2.0));\n"
1171 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1172 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1173 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1174 "#     else\n"
1175 "#      ifdef GL_EXT_gpu_shader4\n"
1176 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1177 "#      else\n"
1178 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1179 "#      endif\n"
1180 "#      if USESHADOWMAPPCF > 1\n"
1181 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1182 "       center *= ShadowMap_TextureScale;\n"
1183 "       vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1184 "       vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
1185 "       vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
1186 "       vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
1187 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1188 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1189 "#      else\n"
1190 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1191 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1192 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1193 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1194 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1195 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1196 "#      endif\n"
1197 "#     endif\n"
1198 "#    else\n"
1199 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1200 "#    endif\n"
1201 "#  endif\n"
1202 "#  ifdef USESHADOWMAPORTHO\n"
1203 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1204 "#  else\n"
1205 "       return f;\n"
1206 "#  endif\n"
1207 "}\n"
1208 "# endif\n"
1209 "\n"
1210 "# ifdef USESHADOWMAPCUBE\n"
1211 "float ShadowMapCompare(vec3 dir)\n"
1212 "{\n"
1213 "       // apply depth texture cubemap as light filter\n"
1214 "       vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1215 "       float f;\n"
1216 "#  ifdef USESHADOWSAMPLER\n"
1217 "       f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1218 "#  else\n"
1219 "       f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1220 "#  endif\n"
1221 "       return f;\n"
1222 "}\n"
1223 "# endif\n"
1224 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1225 "#endif // FRAGMENT_SHADER\n"
1226 "\n"
1227 "\n"
1228 "\n"
1229 "\n"
1230 "#ifdef MODE_DEFERREDGEOMETRY\n"
1231 "#ifdef VERTEX_SHADER\n"
1232 "uniform mat4 TexMatrix;\n"
1233 "#ifdef USEVERTEXTEXTUREBLEND\n"
1234 "uniform mat4 BackgroundTexMatrix;\n"
1235 "#endif\n"
1236 "uniform mat4 ModelViewMatrix;\n"
1237 "void main(void)\n"
1238 "{\n"
1239 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1240 "#ifdef USEVERTEXTEXTUREBLEND\n"
1241 "       gl_FrontColor = gl_Color;\n"
1242 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1243 "#endif\n"
1244 "\n"
1245 "       // transform unnormalized eye direction into tangent space\n"
1246 "#ifdef USEOFFSETMAPPING\n"
1247 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1248 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1249 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1250 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1251 "#endif\n"
1252 "\n"
1253 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1254 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1255 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1256 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1257 "}\n"
1258 "#endif // VERTEX_SHADER\n"
1259 "\n"
1260 "#ifdef FRAGMENT_SHADER\n"
1261 "void main(void)\n"
1262 "{\n"
1263 "#ifdef USEOFFSETMAPPING\n"
1264 "       // apply offsetmapping\n"
1265 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1266 "#define TexCoord TexCoordOffset\n"
1267 "#endif\n"
1268 "\n"
1269 "#ifdef USEALPHAKILL\n"
1270 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1271 "               discard;\n"
1272 "#endif\n"
1273 "\n"
1274 "#ifdef USEVERTEXTEXTUREBLEND\n"
1275 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1276 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1277 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1278 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1279 "#endif\n"
1280 "\n"
1281 "#ifdef USEVERTEXTEXTUREBLEND\n"
1282 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1283 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1284 "#else\n"
1285 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1286 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1287 "#endif\n"
1288 "\n"
1289 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1290 "}\n"
1291 "#endif // FRAGMENT_SHADER\n"
1292 "#else // !MODE_DEFERREDGEOMETRY\n"
1293 "\n"
1294 "\n"
1295 "\n"
1296 "\n"
1297 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1298 "#ifdef VERTEX_SHADER\n"
1299 "uniform mat4 ModelViewMatrix;\n"
1300 "void main(void)\n"
1301 "{\n"
1302 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1303 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1304 "}\n"
1305 "#endif // VERTEX_SHADER\n"
1306 "\n"
1307 "#ifdef FRAGMENT_SHADER\n"
1308 "uniform mat4 ViewToLight;\n"
1309 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1310 "uniform vec2 ScreenToDepth;\n"
1311 "uniform myhalf3 DeferredColor_Ambient;\n"
1312 "uniform myhalf3 DeferredColor_Diffuse;\n"
1313 "#ifdef USESPECULAR\n"
1314 "uniform myhalf3 DeferredColor_Specular;\n"
1315 "uniform myhalf SpecularPower;\n"
1316 "#endif\n"
1317 "uniform myhalf2 PixelToScreenTexCoord;\n"
1318 "void main(void)\n"
1319 "{\n"
1320 "       // calculate viewspace pixel position\n"
1321 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1322 "       vec3 position;\n"
1323 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1324 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1325 "       // decode viewspace pixel normal\n"
1326 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1327 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1328 "       // surfacenormal = pixel normal in viewspace\n"
1329 "       // LightVector = pixel to light in viewspace\n"
1330 "       // CubeVector = position in lightspace\n"
1331 "       // eyevector = pixel to view in viewspace\n"
1332 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1333 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1334 "#ifdef USEDIFFUSE\n"
1335 "       // calculate diffuse shading\n"
1336 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1337 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1338 "#endif\n"
1339 "#ifdef USESPECULAR\n"
1340 "       // calculate directional shading\n"
1341 "       vec3 eyevector = position * -1.0;\n"
1342 "#  ifdef USEEXACTSPECULARMATH\n"
1343 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1344 "#  else\n"
1345 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1346 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1347 "#  endif\n"
1348 "#endif\n"
1349 "\n"
1350 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1351 "       fade *= ShadowMapCompare(CubeVector);\n"
1352 "#endif\n"
1353 "\n"
1354 "#ifdef USEDIFFUSE\n"
1355 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1356 "#else\n"
1357 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1358 "#endif\n"
1359 "#ifdef USESPECULAR\n"
1360 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1361 "#else\n"
1362 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1363 "#endif\n"
1364 "\n"
1365 "# ifdef USECUBEFILTER\n"
1366 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1367 "       gl_FragData[0].rgb *= cubecolor;\n"
1368 "       gl_FragData[1].rgb *= cubecolor;\n"
1369 "# endif\n"
1370 "}\n"
1371 "#endif // FRAGMENT_SHADER\n"
1372 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1373 "\n"
1374 "\n"
1375 "\n"
1376 "\n"
1377 "#ifdef VERTEX_SHADER\n"
1378 "uniform mat4 TexMatrix;\n"
1379 "#ifdef USEVERTEXTEXTUREBLEND\n"
1380 "uniform mat4 BackgroundTexMatrix;\n"
1381 "#endif\n"
1382 "#ifdef MODE_LIGHTSOURCE\n"
1383 "uniform mat4 ModelToLight;\n"
1384 "#endif\n"
1385 "#ifdef USESHADOWMAPORTHO\n"
1386 "uniform mat4 ShadowMapMatrix;\n"
1387 "#endif\n"
1388 "void main(void)\n"
1389 "{\n"
1390 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1391 "       gl_FrontColor = gl_Color;\n"
1392 "#endif\n"
1393 "       // copy the surface texcoord\n"
1394 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1395 "#ifdef USEVERTEXTEXTUREBLEND\n"
1396 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1397 "#endif\n"
1398 "#ifdef USELIGHTMAP\n"
1399 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1400 "#endif\n"
1401 "\n"
1402 "#ifdef MODE_LIGHTSOURCE\n"
1403 "       // transform vertex position into light attenuation/cubemap space\n"
1404 "       // (-1 to +1 across the light box)\n"
1405 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1406 "\n"
1407 "# ifdef USEDIFFUSE\n"
1408 "       // transform unnormalized light direction into tangent space\n"
1409 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1410 "       //  normalize it per pixel)\n"
1411 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1412 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1413 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1414 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1415 "# endif\n"
1416 "#endif\n"
1417 "\n"
1418 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1419 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1420 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1421 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1422 "#endif\n"
1423 "\n"
1424 "       // transform unnormalized eye direction into tangent space\n"
1425 "#ifdef USEEYEVECTOR\n"
1426 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1427 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1428 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1429 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1430 "#endif\n"
1431 "\n"
1432 "#ifdef USEFOG\n"
1433 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1434 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1435 "#endif\n"
1436 "\n"
1437 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1438 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1439 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1440 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1441 "#endif\n"
1442 "\n"
1443 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1444 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1445 "\n"
1446 "#ifdef USESHADOWMAPORTHO\n"
1447 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1448 "#endif\n"
1449 "\n"
1450 "#ifdef USEREFLECTION\n"
1451 "       ModelViewProjectionPosition = gl_Position;\n"
1452 "#endif\n"
1453 "}\n"
1454 "#endif // VERTEX_SHADER\n"
1455 "\n"
1456 "\n"
1457 "\n"
1458 "\n"
1459 "#ifdef FRAGMENT_SHADER\n"
1460 "#ifdef USEDEFERREDLIGHTMAP\n"
1461 "uniform myhalf2 PixelToScreenTexCoord;\n"
1462 "uniform myhalf3 DeferredMod_Diffuse;\n"
1463 "uniform myhalf3 DeferredMod_Specular;\n"
1464 "#endif\n"
1465 "uniform myhalf3 Color_Ambient;\n"
1466 "uniform myhalf3 Color_Diffuse;\n"
1467 "uniform myhalf3 Color_Specular;\n"
1468 "uniform myhalf SpecularPower;\n"
1469 "#ifdef USEGLOW\n"
1470 "uniform myhalf3 Color_Glow;\n"
1471 "#endif\n"
1472 "uniform myhalf Alpha;\n"
1473 "#ifdef USEREFLECTION\n"
1474 "uniform vec4 DistortScaleRefractReflect;\n"
1475 "uniform vec4 ScreenScaleRefractReflect;\n"
1476 "uniform vec4 ScreenCenterRefractReflect;\n"
1477 "uniform myhalf4 ReflectColor;\n"
1478 "#endif\n"
1479 "#ifdef USEREFLECTCUBE\n"
1480 "uniform mat4 ModelToReflectCube;\n"
1481 "uniform sampler2D Texture_ReflectMask;\n"
1482 "uniform samplerCube Texture_ReflectCube;\n"
1483 "#endif\n"
1484 "#ifdef MODE_LIGHTDIRECTION\n"
1485 "uniform myhalf3 LightColor;\n"
1486 "#endif\n"
1487 "#ifdef MODE_LIGHTSOURCE\n"
1488 "uniform myhalf3 LightColor;\n"
1489 "#endif\n"
1490 "void main(void)\n"
1491 "{\n"
1492 "#ifdef USEOFFSETMAPPING\n"
1493 "       // apply offsetmapping\n"
1494 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1495 "#define TexCoord TexCoordOffset\n"
1496 "#endif\n"
1497 "\n"
1498 "       // combine the diffuse textures (base, pants, shirt)\n"
1499 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1500 "#ifdef USEALPHAKILL\n"
1501 "       if (color.a < 0.5)\n"
1502 "               discard;\n"
1503 "#endif\n"
1504 "       color.a *= Alpha;\n"
1505 "#ifdef USECOLORMAPPING\n"
1506 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1507 "#endif\n"
1508 "#ifdef USEVERTEXTEXTUREBLEND\n"
1509 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1510 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1511 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1512 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1513 "       color.a = 1.0;\n"
1514 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1515 "#endif\n"
1516 "\n"
1517 "       // get the surface normal\n"
1518 "#ifdef USEVERTEXTEXTUREBLEND\n"
1519 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1520 "#else\n"
1521 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1522 "#endif\n"
1523 "\n"
1524 "       // get the material colors\n"
1525 "       myhalf3 diffusetex = color.rgb;\n"
1526 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1527 "# ifdef USEVERTEXTEXTUREBLEND\n"
1528 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1529 "# else\n"
1530 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1531 "# endif\n"
1532 "#endif\n"
1533 "\n"
1534 "#ifdef USEREFLECTCUBE\n"
1535 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1536 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1537 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1538 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1539 "#endif\n"
1540 "\n"
1541 "\n"
1542 "\n"
1543 "\n"
1544 "#ifdef MODE_LIGHTSOURCE\n"
1545 "       // light source\n"
1546 "#ifdef USEDIFFUSE\n"
1547 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1548 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1549 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1550 "#ifdef USESPECULAR\n"
1551 "#ifdef USEEXACTSPECULARMATH\n"
1552 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1553 "#else\n"
1554 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1555 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1556 "#endif\n"
1557 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1558 "#endif\n"
1559 "#else\n"
1560 "       color.rgb = diffusetex * Color_Ambient;\n"
1561 "#endif\n"
1562 "       color.rgb *= LightColor;\n"
1563 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1564 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1565 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1566 "#endif\n"
1567 "# ifdef USECUBEFILTER\n"
1568 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1569 "# endif\n"
1570 "#endif // MODE_LIGHTSOURCE\n"
1571 "\n"
1572 "\n"
1573 "\n"
1574 "\n"
1575 "#ifdef MODE_LIGHTDIRECTION\n"
1576 "#define SHADING\n"
1577 "#ifdef USEDIFFUSE\n"
1578 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1579 "#endif\n"
1580 "#define lightcolor LightColor\n"
1581 "#endif // MODE_LIGHTDIRECTION\n"
1582 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1583 "#define SHADING\n"
1584 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1585 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1586 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1587 "       // convert modelspace light vector to tangentspace\n"
1588 "       myhalf3 lightnormal;\n"
1589 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1590 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1591 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1592 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1593 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1594 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1595 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1596 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1597 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1598 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1599 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1600 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1601 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1602 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1603 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1604 "#define SHADING\n"
1605 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1606 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1607 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1608 "#endif\n"
1609 "\n"
1610 "\n"
1611 "\n"
1612 "\n"
1613 "#ifdef MODE_LIGHTMAP\n"
1614 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1615 "#endif // MODE_LIGHTMAP\n"
1616 "#ifdef MODE_VERTEXCOLOR\n"
1617 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1618 "#endif // MODE_VERTEXCOLOR\n"
1619 "#ifdef MODE_FLATCOLOR\n"
1620 "       color.rgb = diffusetex * Color_Ambient;\n"
1621 "#endif // MODE_FLATCOLOR\n"
1622 "\n"
1623 "\n"
1624 "\n"
1625 "\n"
1626 "#ifdef SHADING\n"
1627 "# ifdef USEDIFFUSE\n"
1628 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1629 "#  ifdef USESPECULAR\n"
1630 "#   ifdef USEEXACTSPECULARMATH\n"
1631 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1632 "#   else\n"
1633 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1634 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1635 "#   endif\n"
1636 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1637 "#  else\n"
1638 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1639 "#  endif\n"
1640 "# else\n"
1641 "       color.rgb = diffusetex * Color_Ambient;\n"
1642 "# endif\n"
1643 "#endif\n"
1644 "\n"
1645 "#ifdef USESHADOWMAPORTHO\n"
1646 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1647 "#endif\n"
1648 "\n"
1649 "#ifdef USEDEFERREDLIGHTMAP\n"
1650 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1651 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1652 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1653 "#endif\n"
1654 "\n"
1655 "#ifdef USEGLOW\n"
1656 "#ifdef USEVERTEXTEXTUREBLEND\n"
1657 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1658 "#else\n"
1659 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1660 "#endif\n"
1661 "#endif\n"
1662 "\n"
1663 "#ifdef USEFOG\n"
1664 "#ifdef MODE_LIGHTSOURCE\n"
1665 "       color.rgb *= myhalf(FogVertex());\n"
1666 "#else\n"
1667 "       color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1668 "#endif\n"
1669 "#endif\n"
1670 "\n"
1671 "       // 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"
1672 "#ifdef USEREFLECTION\n"
1673 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1674 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1675 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1676 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1677 "       // FIXME temporary hack to detect the case that the reflection\n"
1678 "       // gets blackened at edges due to leaving the area that contains actual\n"
1679 "       // content.\n"
1680 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1681 "       // 'appening.\n"
1682 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1683 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1684 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1685 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1686 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1687 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1688 "#endif\n"
1689 "\n"
1690 "       gl_FragColor = vec4(color);\n"
1691 "}\n"
1692 "#endif // FRAGMENT_SHADER\n"
1693 "\n"
1694 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1695 "#endif // !MODE_DEFERREDGEOMETRY\n"
1696 "#endif // !MODE_WATER\n"
1697 "#endif // !MODE_REFRACTION\n"
1698 "#endif // !MODE_BLOOMBLUR\n"
1699 "#endif // !MODE_GENERIC\n"
1700 "#endif // !MODE_POSTPROCESS\n"
1701 "#endif // !MODE_SHOWDEPTH\n"
1702 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1703 ;
1704
1705 /*
1706 =========================================================================================================================================================
1707
1708
1709
1710 =========================================================================================================================================================
1711
1712
1713
1714 =========================================================================================================================================================
1715
1716
1717
1718 =========================================================================================================================================================
1719
1720
1721
1722 =========================================================================================================================================================
1723
1724
1725
1726 =========================================================================================================================================================
1727
1728
1729
1730 =========================================================================================================================================================
1731 */
1732
1733 const char *builtincgshaderstring =
1734 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1735 "// written by Forest 'LordHavoc' Hale\n"
1736 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1737 "\n"
1738 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
1739 "# define USEFOG\n"
1740 "#endif\n"
1741 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1742 "#define USELIGHTMAP\n"
1743 "#endif\n"
1744 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
1745 "#define USEEYEVECTOR\n"
1746 "#endif\n"
1747 "\n"
1748 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1749 "#ifdef VERTEX_SHADER\n"
1750 "void main\n"
1751 "(\n"
1752 "float4 gl_Vertex : POSITION,\n"
1753 "uniform float4x4 ModelViewProjectionMatrix,\n"
1754 "out float4 gl_Position : POSITION\n"
1755 ")\n"
1756 "{\n"
1757 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1758 "}\n"
1759 "#endif\n"
1760 "#else // !MODE_DEPTH_ORSHADOW\n"
1761 "\n"
1762 "\n"
1763 "\n"
1764 "\n"
1765 "#ifdef MODE_SHOWDEPTH\n"
1766 "#ifdef VERTEX_SHADER\n"
1767 "void main\n"
1768 "(\n"
1769 "float4 gl_Vertex : POSITION,\n"
1770 "uniform float4x4 ModelViewProjectionMatrix,\n"
1771 "out float4 gl_Position : POSITION,\n"
1772 "out float4 gl_FrontColor : COLOR0\n"
1773 ")\n"
1774 "{\n"
1775 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1776 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1777 "}\n"
1778 "#endif\n"
1779 "\n"
1780 "#ifdef FRAGMENT_SHADER\n"
1781 "void main\n"
1782 "(\n"
1783 "float4 gl_FrontColor : COLOR0,\n"
1784 "out float4 gl_FragColor : COLOR\n"
1785 ")\n"
1786 "{\n"
1787 "       gl_FragColor = gl_FrontColor;\n"
1788 "}\n"
1789 "#endif\n"
1790 "#else // !MODE_SHOWDEPTH\n"
1791 "\n"
1792 "\n"
1793 "\n"
1794 "\n"
1795 "#ifdef MODE_POSTPROCESS\n"
1796 "\n"
1797 "#ifdef VERTEX_SHADER\n"
1798 "void main\n"
1799 "(\n"
1800 "float4 gl_Vertex : POSITION,\n"
1801 "uniform float4x4 ModelViewProjectionMatrix,\n"
1802 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1803 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1804 "out float4 gl_Position : POSITION,\n"
1805 "out float2 TexCoord1 : TEXCOORD0,\n"
1806 "out float2 TexCoord2 : TEXCOORD1\n"
1807 ")\n"
1808 "{\n"
1809 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1810 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1811 "#ifdef USEBLOOM\n"
1812 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1813 "#endif\n"
1814 "}\n"
1815 "#endif\n"
1816 "\n"
1817 "#ifdef FRAGMENT_SHADER\n"
1818 "void main\n"
1819 "(\n"
1820 "float2 TexCoord1 : TEXCOORD0,\n"
1821 "float2 TexCoord2 : TEXCOORD1,\n"
1822 "uniform sampler2D Texture_First,\n"
1823 "#ifdef USEBLOOM\n"
1824 "uniform sampler2D Texture_Second,\n"
1825 "#endif\n"
1826 "#ifdef USEGAMMARAMPS\n"
1827 "uniform sampler2D Texture_GammaRamps,\n"
1828 "#endif\n"
1829 "#ifdef USESATURATION\n"
1830 "uniform float Saturation,\n"
1831 "#endif\n"
1832 "#ifdef USEVIEWTINT\n"
1833 "uniform float4 ViewTintColor,\n"
1834 "#endif\n"
1835 "uniform float4 UserVec1,\n"
1836 "uniform float4 UserVec2,\n"
1837 "uniform float4 UserVec3,\n"
1838 "uniform float4 UserVec4,\n"
1839 "uniform float ClientTime,\n"
1840 "uniform float2 PixelSize,\n"
1841 "out float4 gl_FragColor : COLOR\n"
1842 ")\n"
1843 "{\n"
1844 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1845 "#ifdef USEBLOOM\n"
1846 "       gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
1847 "#endif\n"
1848 "#ifdef USEVIEWTINT\n"
1849 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1850 "#endif\n"
1851 "\n"
1852 "#ifdef USEPOSTPROCESSING\n"
1853 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1854 "// 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"
1855 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1856 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1857 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1858 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
1859 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
1860 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
1861 "#endif\n"
1862 "\n"
1863 "#ifdef USESATURATION\n"
1864 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
1865 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
1866 "       //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
1867 "       gl_FragColor.rgb = lerp(float3(y), gl_FragColor.rgb, Saturation);\n"
1868 "#endif\n"
1869 "\n"
1870 "#ifdef USEGAMMARAMPS\n"
1871 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
1872 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
1873 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
1874 "#endif\n"
1875 "}\n"
1876 "#endif\n"
1877 "#else // !MODE_POSTPROCESS\n"
1878 "\n"
1879 "\n"
1880 "\n"
1881 "\n"
1882 "#ifdef MODE_GENERIC\n"
1883 "#ifdef VERTEX_SHADER\n"
1884 "void main\n"
1885 "(\n"
1886 "float4 gl_Vertex : POSITION,\n"
1887 "uniform float4x4 ModelViewProjectionMatrix,\n"
1888 "float4 gl_Color : COLOR0,\n"
1889 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1890 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1891 "out float4 gl_Position : POSITION,\n"
1892 "out float4 gl_FrontColor : COLOR,\n"
1893 "out float2 TexCoord1 : TEXCOORD0,\n"
1894 "out float2 TexCoord2 : TEXCOORD1\n"
1895 ")\n"
1896 "{\n"
1897 "       gl_FrontColor = gl_Color;\n"
1898 "#ifdef USEDIFFUSE\n"
1899 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1900 "#endif\n"
1901 "#ifdef USESPECULAR\n"
1902 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1903 "#endif\n"
1904 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1905 "}\n"
1906 "#endif\n"
1907 "\n"
1908 "#ifdef FRAGMENT_SHADER\n"
1909 "\n"
1910 "void main\n"
1911 "(\n"
1912 "float4 gl_FrontColor : COLOR,\n"
1913 "float2 TexCoord1 : TEXCOORD0,\n"
1914 "float2 TexCoord2 : TEXCOORD1,\n"
1915 "#ifdef USEDIFFUSE\n"
1916 "uniform sampler2D Texture_First,\n"
1917 "#endif\n"
1918 "#ifdef USESPECULAR\n"
1919 "uniform sampler2D Texture_Second,\n"
1920 "#endif\n"
1921 "out float4 gl_FragColor : COLOR\n"
1922 ")\n"
1923 "{\n"
1924 "       gl_FragColor = gl_FrontColor;\n"
1925 "#ifdef USEDIFFUSE\n"
1926 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
1927 "#endif\n"
1928 "\n"
1929 "#ifdef USESPECULAR\n"
1930 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
1931 "# ifdef USECOLORMAPPING\n"
1932 "       gl_FragColor *= tex2;\n"
1933 "# endif\n"
1934 "# ifdef USEGLOW\n"
1935 "       gl_FragColor += tex2;\n"
1936 "# endif\n"
1937 "# ifdef USEVERTEXTEXTUREBLEND\n"
1938 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
1939 "# endif\n"
1940 "#endif\n"
1941 "}\n"
1942 "#endif\n"
1943 "#else // !MODE_GENERIC\n"
1944 "\n"
1945 "\n"
1946 "\n"
1947 "\n"
1948 "#ifdef MODE_BLOOMBLUR\n"
1949 "#ifdef VERTEX_SHADER\n"
1950 "void main\n"
1951 "(\n"
1952 "float4 gl_Vertex : POSITION,\n"
1953 "uniform float4x4 ModelViewProjectionMatrix,\n"
1954 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1955 "out float4 gl_Position : POSITION,\n"
1956 "out float2 TexCoord : TEXCOORD0\n"
1957 ")\n"
1958 "{\n"
1959 "       TexCoord = gl_MultiTexCoord0.xy;\n"
1960 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1961 "}\n"
1962 "#endif\n"
1963 "\n"
1964 "#ifdef FRAGMENT_SHADER\n"
1965 "\n"
1966 "void main\n"
1967 "(\n"
1968 "float2 TexCoord : TEXCOORD0,\n"
1969 "uniform sampler2D Texture_First,\n"
1970 "uniform float4 BloomBlur_Parameters,\n"
1971 "out float4 gl_FragColor : COLOR\n"
1972 ")\n"
1973 "{\n"
1974 "       int i;\n"
1975 "       float2 tc = TexCoord;\n"
1976 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
1977 "       tc += BloomBlur_Parameters.xy;\n"
1978 "       for (i = 1;i < SAMPLES;i++)\n"
1979 "       {\n"
1980 "               color += tex2D(Texture_First, tc).rgb;\n"
1981 "               tc += BloomBlur_Parameters.xy;\n"
1982 "       }\n"
1983 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
1984 "}\n"
1985 "#endif\n"
1986 "#else // !MODE_BLOOMBLUR\n"
1987 "#ifdef MODE_REFRACTION\n"
1988 "#ifdef VERTEX_SHADER\n"
1989 "void main\n"
1990 "(\n"
1991 "float4 gl_Vertex : POSITION,\n"
1992 "uniform float4x4 ModelViewProjectionMatrix,\n"
1993 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1994 "uniform float4x4 TexMatrix,\n"
1995 "uniform float3 EyePosition,\n"
1996 "out float4 gl_Position : POSITION,\n"
1997 "out float2 TexCoord : TEXCOORD0,\n"
1998 "out float3 EyeVector : TEXCOORD1,\n"
1999 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2000 ")\n"
2001 "{\n"
2002 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2003 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2004 "       ModelViewProjectionPosition = gl_Position;\n"
2005 "}\n"
2006 "#endif\n"
2007 "\n"
2008 "#ifdef FRAGMENT_SHADER\n"
2009 "void main\n"
2010 "(\n"
2011 "float2 TexCoord : TEXCOORD0,\n"
2012 "float3 EyeVector : TEXCOORD1,\n"
2013 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2014 "uniform sampler2D Texture_Normal,\n"
2015 "uniform sampler2D Texture_Refraction,\n"
2016 "uniform sampler2D Texture_Reflection,\n"
2017 "uniform float4 DistortScaleRefractReflect,\n"
2018 "uniform float4 ScreenScaleRefractReflect,\n"
2019 "uniform float4 ScreenCenterRefractReflect,\n"
2020 "uniform float4 RefractColor,\n"
2021 "out float4 gl_FragColor : COLOR\n"
2022 ")\n"
2023 "{\n"
2024 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2025 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2026 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2027 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
2028 "       // FIXME temporary hack to detect the case that the reflection\n"
2029 "       // gets blackened at edges due to leaving the area that contains actual\n"
2030 "       // content.\n"
2031 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2032 "       // 'appening.\n"
2033 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2034 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2035 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2036 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2037 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2038 "       gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2039 "}\n"
2040 "#endif\n"
2041 "#else // !MODE_REFRACTION\n"
2042 "\n"
2043 "\n"
2044 "\n"
2045 "\n"
2046 "#ifdef MODE_WATER\n"
2047 "#ifdef VERTEX_SHADER\n"
2048 "\n"
2049 "void main\n"
2050 "(\n"
2051 "float4 gl_Vertex : POSITION,\n"
2052 "uniform float4x4 ModelViewProjectionMatrix,\n"
2053 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2054 "uniform float4x4 TexMatrix,\n"
2055 "uniform float3 EyePosition,\n"
2056 "out float4 gl_Position : POSITION,\n"
2057 "out float2 TexCoord : TEXCOORD0,\n"
2058 "out float3 EyeVector : TEXCOORD1,\n"
2059 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2060 ")\n"
2061 "{\n"
2062 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2063 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2064 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2065 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2066 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2067 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2068 "       ModelViewProjectionPosition = gl_Position;\n"
2069 "}\n"
2070 "#endif\n"
2071 "\n"
2072 "#ifdef FRAGMENT_SHADER\n"
2073 "void main\n"
2074 "(\n"
2075 "float2 TexCoord : TEXCOORD0,\n"
2076 "float3 EyeVector : TEXCOORD1,\n"
2077 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2078 "uniform sampler2D Texture_Normal,\n"
2079 "uniform sampler2D Texture_Refraction,\n"
2080 "uniform sampler2D Texture_Reflection,\n"
2081 "uniform float4 DistortScaleRefractReflect,\n"
2082 "uniform float4 ScreenScaleRefractReflect,\n"
2083 "uniform float4 ScreenCenterRefractReflect,\n"
2084 "uniform float4 RefractColor,\n"
2085 "uniform float4 ReflectColor,\n"
2086 "uniform float ReflectFactor,\n"
2087 "uniform float ReflectOffset,\n"
2088 "out float4 gl_FragColor : COLOR\n"
2089 ")\n"
2090 "{\n"
2091 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2092 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2093 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2094 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xyxy * DistortScaleRefractReflect;\n"
2095 "       // FIXME temporary hack to detect the case that the reflection\n"
2096 "       // gets blackened at edges due to leaving the area that contains actual\n"
2097 "       // content.\n"
2098 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2099 "       // 'appening.\n"
2100 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2101 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2102 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2103 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2104 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2105 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2106 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2107 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2108 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2109 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2110 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2111 "       gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2112 "}\n"
2113 "#endif\n"
2114 "#else // !MODE_WATER\n"
2115 "\n"
2116 "\n"
2117 "\n"
2118 "\n"
2119 "// 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"
2120 "\n"
2121 "// fragment shader specific:\n"
2122 "#ifdef FRAGMENT_SHADER\n"
2123 "\n"
2124 "#ifdef USEFOG\n"
2125 "float FogVertex(float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask)\n"
2126 "{\n"
2127 "       float fogfrac;\n"
2128 "#ifdef USEFOGOUTSIDE\n"
2129 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2130 "#else\n"
2131 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2132 "#endif\n"
2133 "       return float(tex2D(Texture_FogMask, half2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
2134 "}\n"
2135 "#endif\n"
2136 "\n"
2137 "#ifdef USEOFFSETMAPPING\n"
2138 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler2D Texture_Normal)\n"
2139 "{\n"
2140 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2141 "       // 14 sample relief mapping: linear search and then binary search\n"
2142 "       // this basically steps forward a small amount repeatedly until it finds\n"
2143 "       // itself inside solid, then jitters forward and back using decreasing\n"
2144 "       // amounts to find the impact\n"
2145 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2146 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2147 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2148 "       float3 RT = float3(TexCoord, 1);\n"
2149 "       OffsetVector *= 0.1;\n"
2150 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2151 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2152 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2153 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2154 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2155 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2156 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2157 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2158 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2159 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2160 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2161 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2162 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2163 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2164 "       return RT.xy;\n"
2165 "#else\n"
2166 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2167 "       // this basically moves forward the full distance, and then backs up based\n"
2168 "       // on height of samples\n"
2169 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2170 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2171 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2172 "       TexCoord += OffsetVector;\n"
2173 "       OffsetVector *= 0.333;\n"
2174 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2175 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2176 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2177 "       return TexCoord;\n"
2178 "#endif\n"
2179 "}\n"
2180 "#endif // USEOFFSETMAPPING\n"
2181 "\n"
2182 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2183 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2184 "# ifdef USESHADOWMAPORTHO\n"
2185 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2186 "# else\n"
2187 "#  ifdef USESHADOWMAPVSDCT\n"
2188 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2189 "{\n"
2190 "       float3 adir = abs(dir);\n"
2191 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2192 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2193 "       return float3(lerp(dir.xy, proj.xy, dir.zz) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2194 "}\n"
2195 "#  else\n"
2196 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2197 "{\n"
2198 "       float3 adir = abs(dir);\n"
2199 "       float ma = adir.z;\n"
2200 "       float4 proj = float4(dir, 2.5);\n"
2201 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2202 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2203 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2204 "       return float3(proj.xy * aparams.x + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2205 "}\n"
2206 "#  endif\n"
2207 "# endif\n"
2208 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPORTHO)\n"
2209 "\n"
2210 "#ifdef USESHADOWMAPCUBE\n"
2211 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2212 "{\n"
2213 "    float3 adir = abs(dir);\n"
2214 "    return float4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
2215 "}\n"
2216 "#endif\n"
2217 "\n"
2218 "# ifdef USESHADOWMAPRECT\n"
2219 "#ifdef USESHADOWMAPVSDCT\n"
2220 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2221 "#else\n"
2222 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2223 "#endif\n"
2224 "{\n"
2225 "#ifdef USESHADOWMAPVSDCT\n"
2226 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2227 "#else\n"
2228 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2229 "#endif\n"
2230 "       float f;\n"
2231 "#  ifdef USESHADOWSAMPLER\n"
2232 "\n"
2233 "#    ifdef USESHADOWMAPPCF\n"
2234 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2235 "    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"
2236 "#    else\n"
2237 "    f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2238 "#    endif\n"
2239 "\n"
2240 "#  else\n"
2241 "\n"
2242 "#    ifdef USESHADOWMAPPCF\n"
2243 "#      if USESHADOWMAPPCF > 1\n"
2244 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2245 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2246 "    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"
2247 "    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"
2248 "    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"
2249 "    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"
2250 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2251 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2252 "#      else\n"
2253 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2254 "    float2 offset = frac(shadowmaptc.xy);\n"
2255 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2256 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2257 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2258 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2259 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2260 "#      endif\n"
2261 "#    else\n"
2262 "    f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2263 "#    endif\n"
2264 "\n"
2265 "#  endif\n"
2266 "#  ifdef USESHADOWMAPORTHO\n"
2267 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2268 "#  else\n"
2269 "       return f;\n"
2270 "#  endif\n"
2271 "}\n"
2272 "# endif\n"
2273 "\n"
2274 "# ifdef USESHADOWMAP2D\n"
2275 "#ifdef USESHADOWMAPVSDCT\n"
2276 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2277 "#else\n"
2278 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2279 "#endif\n"
2280 "{\n"
2281 "#ifdef USESHADOWMAPVSDCT\n"
2282 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2283 "#else\n"
2284 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2285 "#endif\n"
2286 "    float f;\n"
2287 "\n"
2288 "#  ifdef USESHADOWSAMPLER\n"
2289 "#    ifdef USESHADOWMAPPCF\n"
2290 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, float3(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
2291 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2292 "    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"
2293 "#    else\n"
2294 "    f = shadow2D(Texture_ShadowMap2D, float3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
2295 "#    endif\n"
2296 "#  else\n"
2297 "#    ifdef USESHADOWMAPPCF\n"
2298 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2299 "#      ifdef GL_ARB_texture_gather\n"
2300 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
2301 "#      else\n"
2302 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2303 "#      endif\n"
2304 "    float2 center = shadowmaptc.xy - 1.5, offset = fract(center);\n"
2305 "    center = (center - offset)*ShadowMap_TextureScale;\n"
2306 "    float4 group1 = step(shadowmaptc.z, texval(0.0, 0.0));\n"
2307 "    float4 group2 = step(shadowmaptc.z, texval(2.0, 0.0));\n"
2308 "    float4 group3 = step(shadowmaptc.z, texval(0.0, 2.0));\n"
2309 "    float4 group4 = step(shadowmaptc.z, texval(2.0, 2.0));\n"
2310 "    float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2311 "                lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2312 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2313 "#     else\n"
2314 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)  \n"
2315 "#      if USESHADOWMAPPCF > 1\n"
2316 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2317 "    center *= ShadowMap_TextureScale;\n"
2318 "    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"
2319 "    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"
2320 "    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"
2321 "    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"
2322 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2323 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2324 "#      else\n"
2325 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2326 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2327 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2328 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2329 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2330 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2331 "#      endif\n"
2332 "#     endif\n"
2333 "#    else\n"
2334 "    f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2335 "#    endif\n"
2336 "#  endif\n"
2337 "#  ifdef USESHADOWMAPORTHO\n"
2338 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2339 "#  else\n"
2340 "       return f;\n"
2341 "#  endif\n"
2342 "}\n"
2343 "# endif\n"
2344 "\n"
2345 "# ifdef USESHADOWMAPCUBE\n"
2346 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2347 "{\n"
2348 "    // apply depth texture cubemap as light filter\n"
2349 "    float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2350 "    float f;\n"
2351 "#  ifdef USESHADOWSAMPLER\n"
2352 "    f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2353 "#  else\n"
2354 "    f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2355 "#  endif\n"
2356 "    return f;\n"
2357 "}\n"
2358 "# endif\n"
2359 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2360 "#endif // FRAGMENT_SHADER\n"
2361 "\n"
2362 "\n"
2363 "\n"
2364 "\n"
2365 "#ifdef MODE_DEFERREDGEOMETRY\n"
2366 "#ifdef VERTEX_SHADER\n"
2367 "void main\n"
2368 "(\n"
2369 "float4 gl_Vertex : POSITION,\n"
2370 "uniform float4x4 ModelViewProjectionMatrix,\n"
2371 "#ifdef USEVERTEXTEXTUREBLEND\n"
2372 "float4 gl_Color : COLOR0,\n"
2373 "#endif\n"
2374 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2375 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2376 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2377 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2378 "uniform float4x4 TexMatrix,\n"
2379 "#ifdef USEVERTEXTEXTUREBLEND\n"
2380 "uniform float4x4 BackgroundTexMatrix,\n"
2381 "#endif\n"
2382 "uniform float4x4 ModelViewMatrix,\n"
2383 "#ifdef USEOFFSETMAPPING\n"
2384 "uniform float3 EyePosition,\n"
2385 "#endif\n"
2386 "out float4 gl_Position : POSITION,\n"
2387 "out float4 gl_FrontColor : COLOR,\n"
2388 "out float4 TexCoordBoth : TEXCOORD0,\n"
2389 "#ifdef USEOFFSETMAPPING\n"
2390 "out float3 EyeVector : TEXCOORD2,\n"
2391 "#endif\n"
2392 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2393 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2394 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2395 ")\n"
2396 "{\n"
2397 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2398 "#ifdef USEVERTEXTEXTUREBLEND\n"
2399 "       gl_FrontColor = gl_Color;\n"
2400 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2401 "#endif\n"
2402 "\n"
2403 "       // transform unnormalized eye direction into tangent space\n"
2404 "#ifdef USEOFFSETMAPPING\n"
2405 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2406 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2407 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2408 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2409 "#endif\n"
2410 "\n"
2411 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2412 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2413 "       VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2414 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2415 "}\n"
2416 "#endif // VERTEX_SHADER\n"
2417 "\n"
2418 "#ifdef FRAGMENT_SHADER\n"
2419 "void main\n"
2420 "(\n"
2421 "float4 TexCoordBoth : TEXCOORD0,\n"
2422 "float3 EyeVector : TEXCOORD2,\n"
2423 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2424 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2425 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2426 "uniform sampler2D Texture_Normal,\n"
2427 "#ifdef USEALPHAKILL\n"
2428 "uniform sampler2D Texture_Color,\n"
2429 "#endif\n"
2430 "uniform sampler2D Texture_Gloss,\n"
2431 "#ifdef USEVERTEXTEXTUREBLEND\n"
2432 "uniform sampler2D Texture_SecondaryNormal,\n"
2433 "uniform sampler2D Texture_SecondaryGloss,\n"
2434 "#endif\n"
2435 "#ifdef USEOFFSETMAPPING\n"
2436 "uniform float OffsetMapping_Scale,\n"
2437 "#endif\n"
2438 "uniform half SpecularPower,\n"
2439 "out float4 gl_FragColor : COLOR\n"
2440 ")\n"
2441 "{\n"
2442 "       float2 TexCoord = TexCoordBoth.xy;\n"
2443 "#ifdef USEOFFSETMAPPING\n"
2444 "       // apply offsetmapping\n"
2445 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2446 "#define TexCoord TexCoordOffset\n"
2447 "#endif\n"
2448 "\n"
2449 "#ifdef USEALPHAKILL\n"
2450 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2451 "               discard;\n"
2452 "#endif\n"
2453 "\n"
2454 "#ifdef USEVERTEXTEXTUREBLEND\n"
2455 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2456 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2457 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2458 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2459 "#endif\n"
2460 "\n"
2461 "#ifdef USEVERTEXTEXTUREBLEND\n"
2462 "       float3 surfacenormal = lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
2463 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2464 "#else\n"
2465 "       float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
2466 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2467 "#endif\n"
2468 "\n"
2469 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), 1);\n"
2470 "}\n"
2471 "#endif // FRAGMENT_SHADER\n"
2472 "#else // !MODE_DEFERREDGEOMETRY\n"
2473 "\n"
2474 "\n"
2475 "\n"
2476 "\n"
2477 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2478 "#ifdef VERTEX_SHADER\n"
2479 "void main\n"
2480 "(\n"
2481 "float4 gl_Vertex : POSITION,\n"
2482 "uniform float4x4 ModelViewProjectionMatrix,\n"
2483 "uniform float4x4 ModelViewMatrix,\n"
2484 "out float4 gl_Position : POSITION,\n"
2485 "out float4 ModelViewPosition : TEXCOORD0\n"
2486 ")\n"
2487 "{\n"
2488 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2489 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2490 "}\n"
2491 "#endif // VERTEX_SHADER\n"
2492 "\n"
2493 "#ifdef FRAGMENT_SHADER\n"
2494 "void main\n"
2495 "(\n"
2496 "float2 Pixel : WPOS,\n"
2497 "float4 ModelViewPosition : TEXCOORD0,\n"
2498 "uniform float4x4 ViewToLight,\n"
2499 "uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2500 "uniform float3 LightPosition,\n"
2501 "uniform half2 PixelToScreenTexCoord,\n"
2502 "uniform half3 DeferredColor_Ambient,\n"
2503 "uniform half3 DeferredColor_Diffuse,\n"
2504 "#ifdef USESPECULAR\n"
2505 "uniform half3 DeferredColor_Specular,\n"
2506 "uniform half SpecularPower,\n"
2507 "#endif\n"
2508 "uniform sampler2D Texture_Attenuation,\n"
2509 "uniform sampler2D Texture_ScreenDepth,\n"
2510 "uniform sampler2D Texture_ScreenNormalMap,\n"
2511 "\n"
2512 "#ifdef USESHADOWMAPRECT\n"
2513 "# ifdef USESHADOWSAMPLER\n"
2514 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2515 "# else\n"
2516 "uniform samplerRECT Texture_ShadowMapRect,\n"
2517 "# endif\n"
2518 "#endif\n"
2519 "\n"
2520 "#ifdef USESHADOWMAP2D\n"
2521 "# ifdef USESHADOWSAMPLER\n"
2522 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2523 "# else\n"
2524 "uniform sampler2D Texture_ShadowMap2D,\n"
2525 "# endif\n"
2526 "#endif\n"
2527 "\n"
2528 "#ifdef USESHADOWMAPVSDCT\n"
2529 "uniform samplerCUBE Texture_CubeProjection,\n"
2530 "#endif\n"
2531 "\n"
2532 "#ifdef USESHADOWMAPCUBE\n"
2533 "# ifdef USESHADOWSAMPLER\n"
2534 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2535 "# else\n"
2536 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2537 "# endif\n"
2538 "#endif\n"
2539 "\n"
2540 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2541 "uniform float2 ShadowMap_TextureScale,\n"
2542 "uniform float4 ShadowMap_Parameters,\n"
2543 "#endif\n"
2544 "\n"
2545 "out float4 gl_FragData0 : COLOR0,\n"
2546 "out float4 gl_FragData1 : COLOR1\n"
2547 ")\n"
2548 "{\n"
2549 "       // calculate viewspace pixel position\n"
2550 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2551 "       ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2552 "       float3 position;\n"
2553 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2554 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2555 "       // decode viewspace pixel normal\n"
2556 "       half4 normalmap = tex2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
2557 "       half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
2558 "       // surfacenormal = pixel normal in viewspace\n"
2559 "       // LightVector = pixel to light in viewspace\n"
2560 "       // CubeVector = position in lightspace\n"
2561 "       // eyevector = pixel to view in viewspace\n"
2562 "       float3 CubeVector = float3(mul(ViewToLight, float4(position,1)));\n"
2563 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2564 "#ifdef USEDIFFUSE\n"
2565 "       // calculate diffuse shading\n"
2566 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2567 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2568 "#endif\n"
2569 "#ifdef USESPECULAR\n"
2570 "       // calculate directional shading\n"
2571 "       float3 eyevector = position * -1.0;\n"
2572 "#  ifdef USEEXACTSPECULARMATH\n"
2573 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
2574 "#  else\n"
2575 "       half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
2576 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
2577 "#  endif\n"
2578 "#endif\n"
2579 "\n"
2580 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2581 "       fade *= ShadowMapCompare(CubeVector,\n"
2582 "# if defined(USESHADOWMAP2D)\n"
2583 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2584 "# endif\n"
2585 "# if defined(USESHADOWMAPRECT)\n"
2586 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2587 "# endif\n"
2588 "# if defined(USESHADOWMAPCUBE)\n"
2589 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2590 "# endif\n"
2591 "\n"
2592 "#ifdef USESHADOWMAPVSDCT\n"
2593 ", Texture_CubeProjection\n"
2594 "#endif\n"
2595 "       );\n"
2596 "#endif\n"
2597 "\n"
2598 "#ifdef USEDIFFUSE\n"
2599 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2600 "#else\n"
2601 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2602 "#endif\n"
2603 "#ifdef USESPECULAR\n"
2604 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2605 "#else\n"
2606 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2607 "#endif\n"
2608 "\n"
2609 "# ifdef USECUBEFILTER\n"
2610 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2611 "       gl_FragData0.rgb *= cubecolor;\n"
2612 "       gl_FragData1.rgb *= cubecolor;\n"
2613 "# endif\n"
2614 "}\n"
2615 "#endif // FRAGMENT_SHADER\n"
2616 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2617 "\n"
2618 "\n"
2619 "\n"
2620 "\n"
2621 "#ifdef VERTEX_SHADER\n"
2622 "void main\n"
2623 "(\n"
2624 "float4 gl_Vertex : POSITION,\n"
2625 "uniform float4x4 ModelViewProjectionMatrix,\n"
2626 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2627 "float4 gl_Color : COLOR0,\n"
2628 "#endif\n"
2629 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2630 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2631 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2632 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2633 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2634 "\n"
2635 "uniform float3 EyePosition,\n"
2636 "uniform float4x4 TexMatrix,\n"
2637 "#ifdef USEVERTEXTEXTUREBLEND\n"
2638 "uniform float4x4 BackgroundTexMatrix,\n"
2639 "#endif\n"
2640 "#ifdef MODE_LIGHTSOURCE\n"
2641 "uniform float4x4 ModelToLight,\n"
2642 "#endif\n"
2643 "#ifdef MODE_LIGHTSOURCE\n"
2644 "uniform float3 LightPosition,\n"
2645 "#endif\n"
2646 "#ifdef MODE_LIGHTDIRECTION\n"
2647 "uniform float3 LightDir,\n"
2648 "#endif\n"
2649 "uniform float4 FogPlane,\n"
2650 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2651 "uniform float3 LightPosition,\n"
2652 "#endif\n"
2653 "#ifdef USESHADOWMAPORTHO\n"
2654 "uniform float4x4 ShadowMapMatrix,\n"
2655 "#endif\n"
2656 "\n"
2657 "out float4 gl_FrontColor : COLOR,\n"
2658 "out float4 TexCoordBoth : TEXCOORD0,\n"
2659 "#ifdef USELIGHTMAP\n"
2660 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2661 "#endif\n"
2662 "#ifdef USEEYEVECTOR\n"
2663 "out float3 EyeVector : TEXCOORD2,\n"
2664 "#endif\n"
2665 "#ifdef USEREFLECTION\n"
2666 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2667 "#endif\n"
2668 "#ifdef USEFOG\n"
2669 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2670 "#endif\n"
2671 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2672 "out float3 LightVector : TEXCOORD1,\n"
2673 "#endif\n"
2674 "#ifdef MODE_LIGHTSOURCE\n"
2675 "out float3 CubeVector : TEXCOORD3,\n"
2676 "#endif\n"
2677 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2678 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2679 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2680 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2681 "#endif\n"
2682 "#ifdef USESHADOWMAPORTHO\n"
2683 "out float3 ShadowMapTC : TEXCOORD8,\n"
2684 "#endif\n"
2685 "out float4 gl_Position : POSITION\n"
2686 ")\n"
2687 "{\n"
2688 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2689 "       gl_FrontColor = gl_Color;\n"
2690 "#endif\n"
2691 "       // copy the surface texcoord\n"
2692 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2693 "#ifdef USEVERTEXTEXTUREBLEND\n"
2694 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2695 "#endif\n"
2696 "#ifdef USELIGHTMAP\n"
2697 "       TexCoordLightmap = float2(gl_MultiTexCoord4);\n"
2698 "#endif\n"
2699 "\n"
2700 "#ifdef MODE_LIGHTSOURCE\n"
2701 "       // transform vertex position into light attenuation/cubemap space\n"
2702 "       // (-1 to +1 across the light box)\n"
2703 "       CubeVector = float3(mul(ModelToLight, gl_Vertex));\n"
2704 "\n"
2705 "# ifdef USEDIFFUSE\n"
2706 "       // transform unnormalized light direction into tangent space\n"
2707 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2708 "       //  normalize it per pixel)\n"
2709 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2710 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2711 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2712 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2713 "# endif\n"
2714 "#endif\n"
2715 "\n"
2716 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2717 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2718 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2719 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2720 "#endif\n"
2721 "\n"
2722 "       // transform unnormalized eye direction into tangent space\n"
2723 "#ifdef USEEYEVECTOR\n"
2724 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2725 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2726 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2727 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2728 "#endif\n"
2729 "\n"
2730 "#ifdef USEFOG\n"
2731 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2732 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2733 "#endif\n"
2734 "\n"
2735 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2736 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2737 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2738 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2739 "#endif\n"
2740 "\n"
2741 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2742 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2743 "\n"
2744 "#ifdef USESHADOWMAPORTHO\n"
2745 "       ShadowMapTC = float3(mul(ShadowMapMatrix, gl_Position));\n"
2746 "#endif\n"
2747 "\n"
2748 "#ifdef USEREFLECTION\n"
2749 "       ModelViewProjectionPosition = gl_Position;\n"
2750 "#endif\n"
2751 "}\n"
2752 "#endif // VERTEX_SHADER\n"
2753 "\n"
2754 "\n"
2755 "\n"
2756 "\n"
2757 "#ifdef FRAGMENT_SHADER\n"
2758 "void main\n"
2759 "(\n"
2760 "#ifdef USEDEFERREDLIGHTMAP\n"
2761 "float2 Pixel : WPOS,\n"
2762 "#endif\n"
2763 "float4 gl_FrontColor : COLOR,\n"
2764 "float4 TexCoordBoth : TEXCOORD0,\n"
2765 "#ifdef USELIGHTMAP\n"
2766 "float2 TexCoordLightmap : TEXCOORD1,\n"
2767 "#endif\n"
2768 "#ifdef USEEYEVECTOR\n"
2769 "float3 EyeVector : TEXCOORD2,\n"
2770 "#endif\n"
2771 "#ifdef USEREFLECTION\n"
2772 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2773 "#endif\n"
2774 "#ifdef USEFOG\n"
2775 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2776 "#endif\n"
2777 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2778 "float3 LightVector : TEXCOORD1,\n"
2779 "#endif\n"
2780 "#ifdef MODE_LIGHTSOURCE\n"
2781 "float3 CubeVector : TEXCOORD3,\n"
2782 "#endif\n"
2783 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2784 "float4 ModelViewPosition : TEXCOORD0,\n"
2785 "#endif\n"
2786 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2787 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2788 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2789 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2790 "#endif\n"
2791 "#ifdef USESHADOWMAPORTHO\n"
2792 "float3 ShadowMapTC : TEXCOORD8,\n"
2793 "#endif\n"
2794 "\n"
2795 "uniform sampler2D Texture_Normal,\n"
2796 "uniform sampler2D Texture_Color,\n"
2797 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2798 "uniform sampler2D Texture_Gloss,\n"
2799 "#endif\n"
2800 "#ifdef USEGLOW\n"
2801 "uniform sampler2D Texture_Glow,\n"
2802 "#endif\n"
2803 "#ifdef USEVERTEXTEXTUREBLEND\n"
2804 "uniform sampler2D Texture_SecondaryNormal,\n"
2805 "uniform sampler2D Texture_SecondaryColor,\n"
2806 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2807 "uniform sampler2D Texture_SecondaryGloss,\n"
2808 "#endif\n"
2809 "#ifdef USEGLOW\n"
2810 "uniform sampler2D Texture_SecondaryGlow,\n"
2811 "#endif\n"
2812 "#endif\n"
2813 "#ifdef USECOLORMAPPING\n"
2814 "uniform sampler2D Texture_Pants,\n"
2815 "uniform sampler2D Texture_Shirt,\n"
2816 "#endif\n"
2817 "#ifdef USEFOG\n"
2818 "uniform sampler2D Texture_FogMask,\n"
2819 "#endif\n"
2820 "#ifdef USELIGHTMAP\n"
2821 "uniform sampler2D Texture_Lightmap,\n"
2822 "#endif\n"
2823 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2824 "uniform sampler2D Texture_Deluxemap,\n"
2825 "#endif\n"
2826 "#ifdef USEREFLECTION\n"
2827 "uniform sampler2D Texture_Reflection,\n"
2828 "#endif\n"
2829 "\n"
2830 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2831 "uniform sampler2D Texture_ScreenDepth,\n"
2832 "uniform sampler2D Texture_ScreenNormalMap,\n"
2833 "#endif\n"
2834 "#ifdef USEDEFERREDLIGHTMAP\n"
2835 "uniform sampler2D Texture_ScreenDiffuse,\n"
2836 "uniform sampler2D Texture_ScreenSpecular,\n"
2837 "#endif\n"
2838 "\n"
2839 "#ifdef USECOLORMAPPING\n"
2840 "uniform half3 Color_Pants,\n"
2841 "uniform half3 Color_Shirt,\n"
2842 "#endif\n"
2843 "#ifdef USEFOG\n"
2844 "uniform float3 FogColor,\n"
2845 "uniform float FogRangeRecip,\n"
2846 "uniform float FogPlaneViewDist,\n"
2847 "uniform float FogHeightFade,\n"
2848 "#endif\n"
2849 "\n"
2850 "#ifdef USEOFFSETMAPPING\n"
2851 "uniform float OffsetMapping_Scale,\n"
2852 "#endif\n"
2853 "\n"
2854 "#ifdef USEDEFERREDLIGHTMAP\n"
2855 "uniform half2 PixelToScreenTexCoord,\n"
2856 "uniform half3 DeferredMod_Diffuse,\n"
2857 "uniform half3 DeferredMod_Specular,\n"
2858 "#endif\n"
2859 "uniform half3 Color_Ambient,\n"
2860 "uniform half3 Color_Diffuse,\n"
2861 "uniform half3 Color_Specular,\n"
2862 "uniform half SpecularPower,\n"
2863 "#ifdef USEGLOW\n"
2864 "uniform half3 Color_Glow,\n"
2865 "#endif\n"
2866 "uniform half Alpha,\n"
2867 "#ifdef USEREFLECTION\n"
2868 "uniform float4 DistortScaleRefractReflect,\n"
2869 "uniform float4 ScreenScaleRefractReflect,\n"
2870 "uniform float4 ScreenCenterRefractReflect,\n"
2871 "uniform half4 ReflectColor,\n"
2872 "#endif\n"
2873 "#ifdef USEREFLECTCUBE\n"
2874 "uniform float4x4 ModelToReflectCube,\n"
2875 "uniform sampler2D Texture_ReflectMask,\n"
2876 "uniform samplerCUBE Texture_ReflectCube,\n"
2877 "#endif\n"
2878 "#ifdef MODE_LIGHTDIRECTION\n"
2879 "uniform half3 LightColor,\n"
2880 "#endif\n"
2881 "#ifdef MODE_LIGHTSOURCE\n"
2882 "uniform half3 LightColor,\n"
2883 "#endif\n"
2884 "\n"
2885 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2886 "uniform sampler2D Texture_Attenuation,\n"
2887 "uniform samplerCUBE Texture_Cube,\n"
2888 "#endif\n"
2889 "\n"
2890 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2891 "\n"
2892 "#ifdef USESHADOWMAPRECT\n"
2893 "# ifdef USESHADOWSAMPLER\n"
2894 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2895 "# else\n"
2896 "uniform samplerRECT Texture_ShadowMapRect,\n"
2897 "# endif\n"
2898 "#endif\n"
2899 "\n"
2900 "#ifdef USESHADOWMAP2D\n"
2901 "# ifdef USESHADOWSAMPLER\n"
2902 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2903 "# else\n"
2904 "uniform sampler2D Texture_ShadowMap2D,\n"
2905 "# endif\n"
2906 "#endif\n"
2907 "\n"
2908 "#ifdef USESHADOWMAPVSDCT\n"
2909 "uniform samplerCUBE Texture_CubeProjection,\n"
2910 "#endif\n"
2911 "\n"
2912 "#ifdef USESHADOWMAPCUBE\n"
2913 "# ifdef USESHADOWSAMPLER\n"
2914 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2915 "# else\n"
2916 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2917 "# endif\n"
2918 "#endif\n"
2919 "\n"
2920 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2921 "uniform float2 ShadowMap_TextureScale,\n"
2922 "uniform float4 ShadowMap_Parameters,\n"
2923 "#endif\n"
2924 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2925 "\n"
2926 "out float4 gl_FragColor : COLOR\n"
2927 ")\n"
2928 "{\n"
2929 "       float2 TexCoord = TexCoordBoth.xy;\n"
2930 "#ifdef USEVERTEXTEXTUREBLEND\n"
2931 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
2932 "#endif\n"
2933 "#ifdef USEOFFSETMAPPING\n"
2934 "       // apply offsetmapping\n"
2935 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2936 "#define TexCoord TexCoordOffset\n"
2937 "#endif\n"
2938 "\n"
2939 "       // combine the diffuse textures (base, pants, shirt)\n"
2940 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
2941 "#ifdef USEALPHAKILL\n"
2942 "       if (color.a < 0.5)\n"
2943 "               discard;\n"
2944 "#endif\n"
2945 "       color.a *= Alpha;\n"
2946 "#ifdef USECOLORMAPPING\n"
2947 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord)) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
2948 "#endif\n"
2949 "#ifdef USEVERTEXTEXTUREBLEND\n"
2950 "       float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
2951 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
2952 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
2953 "       color.rgb = half3(lerp(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
2954 "       color.a = 1.0;\n"
2955 "       //color = lerp(half4(1, 0, 0, 1), color, terrainblend);\n"
2956 "#endif\n"
2957 "\n"
2958 "       // get the surface normal\n"
2959 "#ifdef USEVERTEXTEXTUREBLEND\n"
2960 "       half3 surfacenormal = normalize(half3(lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
2961 "#else\n"
2962 "       half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
2963 "#endif\n"
2964 "\n"
2965 "       // get the material colors\n"
2966 "       half3 diffusetex = color.rgb;\n"
2967 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2968 "# ifdef USEVERTEXTEXTUREBLEND\n"
2969 "       half4 glosstex = half4(lerp(float4(tex2D(Texture_SecondaryGloss, TexCoord2)), float4(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
2970 "# else\n"
2971 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
2972 "# endif\n"
2973 "#endif\n"
2974 "\n"
2975 "#ifdef USEREFLECTCUBE\n"
2976 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
2977 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
2978 "       float3 ReflectCubeTexCoord = float3(mul(ModelToReflectCube, float4(ModelReflectVector, 0)));\n"
2979 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord)) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord));\n"
2980 "#endif\n"
2981 "\n"
2982 "\n"
2983 "\n"
2984 "\n"
2985 "#ifdef MODE_LIGHTSOURCE\n"
2986 "       // light source\n"
2987 "#ifdef USEDIFFUSE\n"
2988 "       half3 lightnormal = half3(normalize(LightVector));\n"
2989 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2990 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
2991 "#ifdef USESPECULAR\n"
2992 "#ifdef USEEXACTSPECULARMATH\n"
2993 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
2994 "#else\n"
2995 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
2996 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
2997 "#endif\n"
2998 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
2999 "#endif\n"
3000 "#else\n"
3001 "       color.rgb = diffusetex * Color_Ambient;\n"
3002 "#endif\n"
3003 "       color.rgb *= LightColor;\n"
3004 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
3005 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
3006 "       color.rgb *= ShadowMapCompare(CubeVector,\n"
3007 "# if defined(USESHADOWMAP2D)\n"
3008 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3009 "# endif\n"
3010 "# if defined(USESHADOWMAPRECT)\n"
3011 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3012 "# endif\n"
3013 "# if defined(USESHADOWMAPCUBE)\n"
3014 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
3015 "# endif\n"
3016 "\n"
3017 "#ifdef USESHADOWMAPVSDCT\n"
3018 ", Texture_CubeProjection\n"
3019 "#endif\n"
3020 "       );\n"
3021 "\n"
3022 "#endif\n"
3023 "# ifdef USECUBEFILTER\n"
3024 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector));\n"
3025 "# endif\n"
3026 "#endif // MODE_LIGHTSOURCE\n"
3027 "\n"
3028 "\n"
3029 "\n"
3030 "\n"
3031 "#ifdef MODE_LIGHTDIRECTION\n"
3032 "#define SHADING\n"
3033 "#ifdef USEDIFFUSE\n"
3034 "       half3 lightnormal = half3(normalize(LightVector));\n"
3035 "#endif\n"
3036 "#define lightcolor LightColor\n"
3037 "#endif // MODE_LIGHTDIRECTION\n"
3038 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3039 "#define SHADING\n"
3040 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3041 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3042 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3043 "       // convert modelspace light vector to tangentspace\n"
3044 "       half3 lightnormal;\n"
3045 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3046 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3047 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3048 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3049 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3050 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3051 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3052 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3053 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3054 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3055 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3056 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3057 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3058 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3059 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3060 "#define SHADING\n"
3061 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3062 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3063 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3064 "#endif\n"
3065 "\n"
3066 "\n"
3067 "\n"
3068 "\n"
3069 "#ifdef MODE_LIGHTMAP\n"
3070 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
3071 "#endif // MODE_LIGHTMAP\n"
3072 "#ifdef MODE_VERTEXCOLOR\n"
3073 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3074 "#endif // MODE_VERTEXCOLOR\n"
3075 "#ifdef MODE_FLATCOLOR\n"
3076 "       color.rgb = diffusetex * Color_Ambient;\n"
3077 "#endif // MODE_FLATCOLOR\n"
3078 "\n"
3079 "\n"
3080 "\n"
3081 "\n"
3082 "#ifdef SHADING\n"
3083 "# ifdef USEDIFFUSE\n"
3084 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3085 "#  ifdef USESPECULAR\n"
3086 "#   ifdef USEEXACTSPECULARMATH\n"
3087 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
3088 "#   else\n"
3089 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3090 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
3091 "#   endif\n"
3092 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3093 "#  else\n"
3094 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3095 "#  endif\n"
3096 "# else\n"
3097 "       color.rgb = diffusetex * Color_Ambient;\n"
3098 "# endif\n"
3099 "#endif\n"
3100 "\n"
3101 "#ifdef USESHADOWMAPORTHO\n"
3102 "       color.rgb *= ShadowMapCompare(ShadowMapTC,\n"
3103 "# if defined(USESHADOWMAP2D)\n"
3104 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3105 "# endif\n"
3106 "# if defined(USESHADOWMAPRECT)\n"
3107 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3108 "# endif\n"
3109 "       );\n"
3110 "#endif\n"
3111 "\n"
3112 "#ifdef USEDEFERREDLIGHTMAP\n"
3113 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3114 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
3115 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
3116 "#endif\n"
3117 "\n"
3118 "#ifdef USEGLOW\n"
3119 "#ifdef USEVERTEXTEXTUREBLEND\n"
3120 "       color.rgb += lerp(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
3121 "#else\n"
3122 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
3123 "#endif\n"
3124 "#endif\n"
3125 "\n"
3126 "#ifdef USEFOG\n"
3127 "#ifdef MODE_LIGHTSOURCE\n"
3128 "       color.rgb *= half(FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3129 "#else\n"
3130 "       color.rgb = lerp(FogColor, float3(color.rgb), FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3131 "#endif\n"
3132 "#endif\n"
3133 "\n"
3134 "       // 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"
3135 "#ifdef USEREFLECTION\n"
3136 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3137 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3138 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3139 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
3140 "       // FIXME temporary hack to detect the case that the reflection\n"
3141 "       // gets blackened at edges due to leaving the area that contains actual\n"
3142 "       // content.\n"
3143 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3144 "       // 'appening.\n"
3145 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3146 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3147 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3148 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3149 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3150 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
3151 "#endif\n"
3152 "\n"
3153 "       gl_FragColor = float4(color);\n"
3154 "}\n"
3155 "#endif // FRAGMENT_SHADER\n"
3156 "\n"
3157 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3158 "#endif // !MODE_DEFERREDGEOMETRY\n"
3159 "#endif // !MODE_WATER\n"
3160 "#endif // !MODE_REFRACTION\n"
3161 "#endif // !MODE_BLOOMBLUR\n"
3162 "#endif // !MODE_GENERIC\n"
3163 "#endif // !MODE_POSTPROCESS\n"
3164 "#endif // !MODE_SHOWDEPTH\n"
3165 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3166 ;
3167
3168 char *glslshaderstring = NULL;
3169 char *cgshaderstring = NULL;
3170
3171 //=======================================================================================================================================================
3172
3173 typedef struct shaderpermutationinfo_s
3174 {
3175         const char *pretext;
3176         const char *name;
3177 }
3178 shaderpermutationinfo_t;
3179
3180 typedef struct shadermodeinfo_s
3181 {
3182         const char *vertexfilename;
3183         const char *geometryfilename;
3184         const char *fragmentfilename;
3185         const char *pretext;
3186         const char *name;
3187 }
3188 shadermodeinfo_t;
3189
3190 typedef enum shaderpermutation_e
3191 {
3192         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3193         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3194         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3195         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3196         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3197         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3198         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3199         SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
3200         SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
3201         SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
3202         SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
3203         SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
3204         SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
3205         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3206         SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3207         SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3208         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3209         SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
3210         SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
3211         SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
3212         SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
3213         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3214         SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
3215         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3216         SHADERPERMUTATION_SHADOWMAPORTHO = 1<<24, //< (lightsource) use orthographic shadowmap projection
3217         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<25, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3218         SHADERPERMUTATION_ALPHAKILL = 1<<26, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3219         SHADERPERMUTATION_REFLECTCUBE = 1<<27, ///< fake reflections using global cubemap (not HDRI light probe)
3220         SHADERPERMUTATION_LIMIT = 1<<28, ///< size of permutations array
3221         SHADERPERMUTATION_COUNT = 28 ///< size of shaderpermutationinfo array
3222 }
3223 shaderpermutation_t;
3224
3225 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3226 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3227 {
3228         {"#define USEDIFFUSE\n", " diffuse"},
3229         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3230         {"#define USEVIEWTINT\n", " viewtint"},
3231         {"#define USECOLORMAPPING\n", " colormapping"},
3232         {"#define USESATURATION\n", " saturation"},
3233         {"#define USEFOGINSIDE\n", " foginside"},
3234         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3235         {"#define USEGAMMARAMPS\n", " gammaramps"},
3236         {"#define USECUBEFILTER\n", " cubefilter"},
3237         {"#define USEGLOW\n", " glow"},
3238         {"#define USEBLOOM\n", " bloom"},
3239         {"#define USESPECULAR\n", " specular"},
3240         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3241         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3242         {"#define USEREFLECTION\n", " reflection"},
3243         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3244         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3245         {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3246         {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3247         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3248         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3249         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3250         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3251         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3252         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3253         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3254         {"#define USEALPHAKILL\n", " alphakill"},
3255         {"#define USEREFLECTCUBE\n", " reflectcube"},
3256 };
3257
3258 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3259 typedef enum shadermode_e
3260 {
3261         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3262         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3263         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3264         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3265         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3266         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3267         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3268         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3269         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3270         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3271         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3272         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3273         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3274         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3275         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3276         SHADERMODE_COUNT
3277 }
3278 shadermode_t;
3279
3280 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3281 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3282 {
3283         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3284         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3285         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3286         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3287         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3288         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3289         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3290         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3291         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3292         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3293         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3294         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3295         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3296         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3297         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3298 };
3299
3300 #ifdef SUPPORTCG
3301 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3302 {
3303         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3304         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3305         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3306         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3307         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3308         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3309         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3310         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3311         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3312         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3313         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3314         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3315         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3316         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3317         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3318 };
3319 #endif
3320
3321 struct r_glsl_permutation_s;
3322 typedef struct r_glsl_permutation_s
3323 {
3324         /// hash lookup data
3325         struct r_glsl_permutation_s *hashnext;
3326         unsigned int mode;
3327         unsigned int permutation;
3328
3329         /// indicates if we have tried compiling this permutation already
3330         qboolean compiled;
3331         /// 0 if compilation failed
3332         int program;
3333         /// locations of detected uniforms in program object, or -1 if not found
3334         int loc_Texture_First;
3335         int loc_Texture_Second;
3336         int loc_Texture_GammaRamps;
3337         int loc_Texture_Normal;
3338         int loc_Texture_Color;
3339         int loc_Texture_Gloss;
3340         int loc_Texture_Glow;
3341         int loc_Texture_SecondaryNormal;
3342         int loc_Texture_SecondaryColor;
3343         int loc_Texture_SecondaryGloss;
3344         int loc_Texture_SecondaryGlow;
3345         int loc_Texture_Pants;
3346         int loc_Texture_Shirt;
3347         int loc_Texture_FogMask;
3348         int loc_Texture_Lightmap;
3349         int loc_Texture_Deluxemap;
3350         int loc_Texture_Attenuation;
3351         int loc_Texture_Cube;
3352         int loc_Texture_Refraction;
3353         int loc_Texture_Reflection;
3354         int loc_Texture_ShadowMapRect;
3355         int loc_Texture_ShadowMapCube;
3356         int loc_Texture_ShadowMap2D;
3357         int loc_Texture_CubeProjection;
3358         int loc_Texture_ScreenDepth;
3359         int loc_Texture_ScreenNormalMap;
3360         int loc_Texture_ScreenDiffuse;
3361         int loc_Texture_ScreenSpecular;
3362         int loc_Texture_ReflectMask;
3363         int loc_Texture_ReflectCube;
3364         int loc_Alpha;
3365         int loc_BloomBlur_Parameters;
3366         int loc_ClientTime;
3367         int loc_Color_Ambient;
3368         int loc_Color_Diffuse;
3369         int loc_Color_Specular;
3370         int loc_Color_Glow;
3371         int loc_Color_Pants;
3372         int loc_Color_Shirt;
3373         int loc_DeferredColor_Ambient;
3374         int loc_DeferredColor_Diffuse;
3375         int loc_DeferredColor_Specular;
3376         int loc_DeferredMod_Diffuse;
3377         int loc_DeferredMod_Specular;
3378         int loc_DistortScaleRefractReflect;
3379         int loc_EyePosition;
3380         int loc_FogColor;
3381         int loc_FogHeightFade;
3382         int loc_FogPlane;
3383         int loc_FogPlaneViewDist;
3384         int loc_FogRangeRecip;
3385         int loc_LightColor;
3386         int loc_LightDir;
3387         int loc_LightPosition;
3388         int loc_OffsetMapping_Scale;
3389         int loc_PixelSize;
3390         int loc_ReflectColor;
3391         int loc_ReflectFactor;
3392         int loc_ReflectOffset;
3393         int loc_RefractColor;
3394         int loc_Saturation;
3395         int loc_ScreenCenterRefractReflect;
3396         int loc_ScreenScaleRefractReflect;
3397         int loc_ScreenToDepth;
3398         int loc_ShadowMap_Parameters;
3399         int loc_ShadowMap_TextureScale;
3400         int loc_SpecularPower;
3401         int loc_UserVec1;
3402         int loc_UserVec2;
3403         int loc_UserVec3;
3404         int loc_UserVec4;
3405         int loc_ViewTintColor;
3406         int loc_ViewToLight;
3407         int loc_ModelToLight;
3408         int loc_TexMatrix;
3409         int loc_BackgroundTexMatrix;
3410         int loc_ModelViewProjectionMatrix;
3411         int loc_ModelViewMatrix;
3412         int loc_PixelToScreenTexCoord;
3413         int loc_ModelToReflectCube;
3414         int loc_ShadowMapMatrix;        
3415 }
3416 r_glsl_permutation_t;
3417
3418 #define SHADERPERMUTATION_HASHSIZE 256
3419
3420 /// information about each possible shader permutation
3421 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3422 /// currently selected permutation
3423 r_glsl_permutation_t *r_glsl_permutation;
3424 /// storage for permutations linked in the hash table
3425 memexpandablearray_t r_glsl_permutationarray;
3426
3427 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3428 {
3429         //unsigned int hashdepth = 0;
3430         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3431         r_glsl_permutation_t *p;
3432         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3433         {
3434                 if (p->mode == mode && p->permutation == permutation)
3435                 {
3436                         //if (hashdepth > 10)
3437                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3438                         return p;
3439                 }
3440                 //hashdepth++;
3441         }
3442         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3443         p->mode = mode;
3444         p->permutation = permutation;
3445         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3446         r_glsl_permutationhash[mode][hashindex] = p;
3447         //if (hashdepth > 10)
3448         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3449         return p;
3450 }
3451
3452 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3453 {
3454         char *shaderstring;
3455         if (!filename || !filename[0])
3456                 return NULL;
3457         if (!strcmp(filename, "glsl/default.glsl"))
3458         {
3459                 if (!glslshaderstring)
3460                 {
3461                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3462                         if (glslshaderstring)
3463                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3464                         else
3465                                 glslshaderstring = (char *)builtinshaderstring;
3466                 }
3467                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3468                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3469                 return shaderstring;
3470         }
3471         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3472         if (shaderstring)
3473         {
3474                 if (printfromdisknotice)
3475                         Con_DPrintf("from disk %s... ", filename);
3476                 return shaderstring;
3477         }
3478         return shaderstring;
3479 }
3480
3481 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3482 {
3483         int i;
3484         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3485         int vertstrings_count = 0;
3486         int geomstrings_count = 0;
3487         int fragstrings_count = 0;
3488         char *vertexstring, *geometrystring, *fragmentstring;
3489         const char *vertstrings_list[32+3];
3490         const char *geomstrings_list[32+3];
3491         const char *fragstrings_list[32+3];
3492         char permutationname[256];
3493
3494         if (p->compiled)
3495                 return;
3496         p->compiled = true;
3497         p->program = 0;
3498
3499         permutationname[0] = 0;
3500         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3501         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3502         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3503
3504         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3505
3506         // the first pretext is which type of shader to compile as
3507         // (later these will all be bound together as a program object)
3508         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3509         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3510         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3511
3512         // the second pretext is the mode (for example a light source)
3513         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3514         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3515         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3516         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3517
3518         // now add all the permutation pretexts
3519         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3520         {
3521                 if (permutation & (1<<i))
3522                 {
3523                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3524                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3525                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3526                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3527                 }
3528                 else
3529                 {
3530                         // keep line numbers correct
3531                         vertstrings_list[vertstrings_count++] = "\n";
3532                         geomstrings_list[geomstrings_count++] = "\n";
3533                         fragstrings_list[fragstrings_count++] = "\n";
3534                 }
3535         }
3536
3537         // now append the shader text itself
3538         vertstrings_list[vertstrings_count++] = vertexstring;
3539         geomstrings_list[geomstrings_count++] = geometrystring;
3540         fragstrings_list[fragstrings_count++] = fragmentstring;
3541
3542         // if any sources were NULL, clear the respective list
3543         if (!vertexstring)
3544                 vertstrings_count = 0;
3545         if (!geometrystring)
3546                 geomstrings_count = 0;
3547         if (!fragmentstring)
3548                 fragstrings_count = 0;
3549
3550         // compile the shader program
3551         if (vertstrings_count + geomstrings_count + fragstrings_count)
3552                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3553         if (p->program)
3554         {
3555                 CHECKGLERROR
3556                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3557                 // look up all the uniform variable names we care about, so we don't
3558                 // have to look them up every time we set them
3559
3560                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3561                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3562                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3563                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3564                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3565                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3566                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3567                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3568                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3569                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3570                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3571                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3572                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3573                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3574                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3575                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3576                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3577                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3578                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3579                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3580                 p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3581                 p->loc_Texture_ShadowMapCube      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3582                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3583                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3584                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3585                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3586                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3587                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3588                 p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3589                 p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3590                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3591                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3592                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3593                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3594                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3595                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3596                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3597                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3598                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3599                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3600                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3601                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3602                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3603                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3604                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3605                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3606                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3607                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3608                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3609                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3610                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3611                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3612                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3613                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3614                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3615                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3616                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3617                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3618                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3619                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3620                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3621                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3622                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3623                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3624                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3625                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3626                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3627                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3628                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3629                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3630                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3631                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3632                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3633                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3634                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3635                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3636                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3637                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3638                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3639                 p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3640                 p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");            
3641                 // initialize the samplers to refer to the texture units we use
3642                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3643                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3644                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3645                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3646                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3647                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3648                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3649                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3650                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3651                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3652                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3653                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3654                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3655                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3656                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3657                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3658                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3659                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3660                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3661                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3662                 if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT);
3663                 if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
3664                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D);
3665                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3666                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3667                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3668                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3669                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3670                 if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
3671                 if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
3672                 CHECKGLERROR
3673                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3674         }
3675         else
3676                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3677
3678         // free the strings
3679         if (vertexstring)
3680                 Mem_Free(vertexstring);
3681         if (geometrystring)
3682                 Mem_Free(geometrystring);
3683         if (fragmentstring)
3684                 Mem_Free(fragmentstring);
3685 }
3686
3687 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3688 {
3689         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3690         if (r_glsl_permutation != perm)
3691         {
3692                 r_glsl_permutation = perm;
3693                 if (!r_glsl_permutation->program)
3694                 {
3695                         if (!r_glsl_permutation->compiled)
3696                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3697                         if (!r_glsl_permutation->program)
3698                         {
3699                                 // remove features until we find a valid permutation
3700                                 int i;
3701                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3702                                 {
3703                                         // reduce i more quickly whenever it would not remove any bits
3704                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3705                                         if (!(permutation & j))
3706                                                 continue;
3707                                         permutation -= j;
3708                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3709                                         if (!r_glsl_permutation->compiled)
3710                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3711                                         if (r_glsl_permutation->program)
3712                                                 break;
3713                                 }
3714                                 if (i >= SHADERPERMUTATION_COUNT)
3715                                 {
3716                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3717                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3718                                         qglUseProgramObjectARB(0);CHECKGLERROR
3719                                         return; // no bit left to clear, entire mode is broken
3720                                 }
3721                         }
3722                 }
3723                 CHECKGLERROR
3724                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3725         }
3726         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3727         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3728         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3729 }
3730
3731 #ifdef SUPPORTCG
3732 #include <Cg/cgGL.h>
3733 struct r_cg_permutation_s;
3734 typedef struct r_cg_permutation_s
3735 {
3736         /// hash lookup data
3737         struct r_cg_permutation_s *hashnext;
3738         unsigned int mode;
3739         unsigned int permutation;
3740
3741         /// indicates if we have tried compiling this permutation already
3742         qboolean compiled;
3743         /// 0 if compilation failed
3744         CGprogram vprogram;
3745         CGprogram fprogram;
3746         /// locations of detected parameters in programs, or NULL if not found
3747         CGparameter vp_EyePosition;
3748         CGparameter vp_FogPlane;
3749         CGparameter vp_LightDir;
3750         CGparameter vp_LightPosition;
3751         CGparameter vp_ModelToLight;
3752         CGparameter vp_TexMatrix;
3753         CGparameter vp_BackgroundTexMatrix;
3754         CGparameter vp_ModelViewProjectionMatrix;
3755         CGparameter vp_ModelViewMatrix;
3756         CGparameter vp_ShadowMapMatrix;
3757
3758         CGparameter fp_Texture_First;
3759         CGparameter fp_Texture_Second;
3760         CGparameter fp_Texture_GammaRamps;
3761         CGparameter fp_Texture_Normal;
3762         CGparameter fp_Texture_Color;
3763         CGparameter fp_Texture_Gloss;
3764         CGparameter fp_Texture_Glow;
3765         CGparameter fp_Texture_SecondaryNormal;
3766         CGparameter fp_Texture_SecondaryColor;
3767         CGparameter fp_Texture_SecondaryGloss;
3768         CGparameter fp_Texture_SecondaryGlow;
3769         CGparameter fp_Texture_Pants;
3770         CGparameter fp_Texture_Shirt;
3771         CGparameter fp_Texture_FogMask;
3772         CGparameter fp_Texture_Lightmap;
3773         CGparameter fp_Texture_Deluxemap;
3774         CGparameter fp_Texture_Attenuation;
3775         CGparameter fp_Texture_Cube;
3776         CGparameter fp_Texture_Refraction;
3777         CGparameter fp_Texture_Reflection;
3778         CGparameter fp_Texture_ShadowMapRect;
3779         CGparameter fp_Texture_ShadowMapCube;
3780         CGparameter fp_Texture_ShadowMap2D;
3781         CGparameter fp_Texture_CubeProjection;
3782         CGparameter fp_Texture_ScreenDepth;
3783         CGparameter fp_Texture_ScreenNormalMap;
3784         CGparameter fp_Texture_ScreenDiffuse;
3785         CGparameter fp_Texture_ScreenSpecular;
3786         CGparameter fp_Texture_ReflectMask;
3787         CGparameter fp_Texture_ReflectCube;
3788         CGparameter fp_Alpha;
3789         CGparameter fp_BloomBlur_Parameters;
3790         CGparameter fp_ClientTime;
3791         CGparameter fp_Color_Ambient;
3792         CGparameter fp_Color_Diffuse;
3793         CGparameter fp_Color_Specular;
3794         CGparameter fp_Color_Glow;
3795         CGparameter fp_Color_Pants;
3796         CGparameter fp_Color_Shirt;
3797         CGparameter fp_DeferredColor_Ambient;
3798         CGparameter fp_DeferredColor_Diffuse;
3799         CGparameter fp_DeferredColor_Specular;
3800         CGparameter fp_DeferredMod_Diffuse;
3801         CGparameter fp_DeferredMod_Specular;
3802         CGparameter fp_DistortScaleRefractReflect;
3803         CGparameter fp_EyePosition;
3804         CGparameter fp_FogColor;
3805         CGparameter fp_FogHeightFade;
3806         CGparameter fp_FogPlane;
3807         CGparameter fp_FogPlaneViewDist;
3808         CGparameter fp_FogRangeRecip;
3809         CGparameter fp_LightColor;
3810         CGparameter fp_LightDir;
3811         CGparameter fp_LightPosition;
3812         CGparameter fp_OffsetMapping_Scale;
3813         CGparameter fp_PixelSize;
3814         CGparameter fp_ReflectColor;
3815         CGparameter fp_ReflectFactor;
3816         CGparameter fp_ReflectOffset;
3817         CGparameter fp_RefractColor;
3818         CGparameter fp_Saturation;
3819         CGparameter fp_ScreenCenterRefractReflect;
3820         CGparameter fp_ScreenScaleRefractReflect;
3821         CGparameter fp_ScreenToDepth;
3822         CGparameter fp_ShadowMap_Parameters;
3823         CGparameter fp_ShadowMap_TextureScale;
3824         CGparameter fp_SpecularPower;
3825         CGparameter fp_UserVec1;
3826         CGparameter fp_UserVec2;
3827         CGparameter fp_UserVec3;
3828         CGparameter fp_UserVec4;
3829         CGparameter fp_ViewTintColor;
3830         CGparameter fp_ViewToLight;
3831         CGparameter fp_PixelToScreenTexCoord;
3832         CGparameter fp_ModelToReflectCube;
3833 }
3834 r_cg_permutation_t;
3835
3836 /// information about each possible shader permutation
3837 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3838 /// currently selected permutation
3839 r_cg_permutation_t *r_cg_permutation;
3840 /// storage for permutations linked in the hash table
3841 memexpandablearray_t r_cg_permutationarray;
3842
3843 #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));}}
3844
3845 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3846 {
3847         //unsigned int hashdepth = 0;
3848         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3849         r_cg_permutation_t *p;
3850         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3851         {
3852                 if (p->mode == mode && p->permutation == permutation)
3853                 {
3854                         //if (hashdepth > 10)
3855                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3856                         return p;
3857                 }
3858                 //hashdepth++;
3859         }
3860         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3861         p->mode = mode;
3862         p->permutation = permutation;
3863         p->hashnext = r_cg_permutationhash[mode][hashindex];
3864         r_cg_permutationhash[mode][hashindex] = p;
3865         //if (hashdepth > 10)
3866         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3867         return p;
3868 }
3869
3870 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3871 {
3872         char *shaderstring;
3873         if (!filename || !filename[0])
3874                 return NULL;
3875         if (!strcmp(filename, "cg/default.cg"))
3876         {
3877                 if (!cgshaderstring)
3878                 {
3879                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3880                         if (cgshaderstring)
3881                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3882                         else
3883                                 cgshaderstring = (char *)builtincgshaderstring;
3884                 }
3885                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
3886                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
3887                 return shaderstring;
3888         }
3889         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3890         if (shaderstring)
3891         {
3892                 if (printfromdisknotice)
3893                         Con_DPrintf("from disk %s... ", filename);
3894                 return shaderstring;
3895         }
3896         return shaderstring;
3897 }
3898
3899 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
3900 {
3901         // TODO: load or create .fp and .vp shader files
3902 }
3903
3904 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
3905 {
3906         int i;
3907         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
3908         int vertstrings_count = 0, vertstring_length = 0;
3909         int geomstrings_count = 0, geomstring_length = 0;
3910         int fragstrings_count = 0, fragstring_length = 0;
3911         char *t;
3912         char *vertexstring, *geometrystring, *fragmentstring;
3913         char *vertstring, *geomstring, *fragstring;
3914         const char *vertstrings_list[32+3];
3915         const char *geomstrings_list[32+3];
3916         const char *fragstrings_list[32+3];
3917         char permutationname[256];
3918         char cachename[256];
3919         CGprofile vertexProfile;
3920         CGprofile fragmentProfile;
3921
3922         if (p->compiled)
3923                 return;
3924         p->compiled = true;
3925         p->vprogram = NULL;
3926         p->fprogram = NULL;
3927
3928         permutationname[0] = 0;
3929         cachename[0] = 0;
3930         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
3931         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
3932         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
3933
3934         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3935         strlcat(cachename, "cg/", sizeof(cachename));
3936
3937         // the first pretext is which type of shader to compile as
3938         // (later these will all be bound together as a program object)
3939         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3940         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3941         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3942
3943         // the second pretext is the mode (for example a light source)
3944         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3945         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3946         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3947         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3948         strlcat(cachename, modeinfo->name, sizeof(cachename));
3949
3950         // now add all the permutation pretexts
3951         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3952         {
3953                 if (permutation & (1<<i))
3954                 {
3955                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3956                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3957                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3958                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3959                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
3960                 }
3961                 else
3962                 {
3963                         // keep line numbers correct
3964                         vertstrings_list[vertstrings_count++] = "\n";
3965                         geomstrings_list[geomstrings_count++] = "\n";
3966                         fragstrings_list[fragstrings_count++] = "\n";
3967                 }
3968         }
3969
3970         // replace spaces in the cachename with _ characters
3971         for (i = 0;cachename[i];i++)
3972                 if (cachename[i] == ' ')
3973                         cachename[i] = '_';
3974
3975         // now append the shader text itself
3976         vertstrings_list[vertstrings_count++] = vertexstring;
3977         geomstrings_list[geomstrings_count++] = geometrystring;
3978         fragstrings_list[fragstrings_count++] = fragmentstring;
3979
3980         // if any sources were NULL, clear the respective list
3981         if (!vertexstring)
3982                 vertstrings_count = 0;
3983         if (!geometrystring)
3984                 geomstrings_count = 0;
3985         if (!fragmentstring)
3986                 fragstrings_count = 0;
3987
3988         vertstring_length = 0;
3989         for (i = 0;i < vertstrings_count;i++)
3990                 vertstring_length += strlen(vertstrings_list[i]);
3991         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
3992         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
3993                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
3994
3995         geomstring_length = 0;
3996         for (i = 0;i < geomstrings_count;i++)
3997                 geomstring_length += strlen(geomstrings_list[i]);
3998         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
3999         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4000                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4001
4002         fragstring_length = 0;
4003         for (i = 0;i < fragstrings_count;i++)
4004                 fragstring_length += strlen(fragstrings_list[i]);
4005         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4006         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4007                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4008
4009         CHECKGLERROR
4010         CHECKCGERROR
4011         //vertexProfile = CG_PROFILE_ARBVP1;
4012         //fragmentProfile = CG_PROFILE_ARBFP1;
4013         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4014         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4015         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4016         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4017         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4018         CHECKGLERROR
4019
4020         // try to load the cached shader, or generate one
4021         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4022
4023         // if caching failed, do a dynamic compile for now
4024         CHECKCGERROR
4025         if (vertstring[0] && !p->vprogram)
4026                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4027         CHECKCGERROR
4028         if (fragstring[0] && !p->fprogram)
4029                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4030         CHECKCGERROR
4031
4032         // look up all the uniform variable names we care about, so we don't
4033         // have to look them up every time we set them
4034         if (p->vprogram)
4035         {
4036                 CHECKCGERROR
4037                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4038                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4039                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4040                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4041                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4042                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4043                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4044                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4045                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4046                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4047                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4048                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4049                 CHECKCGERROR
4050         }
4051         if (p->fprogram)
4052         {
4053                 CHECKCGERROR
4054                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4055                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4056                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4057                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4058                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4059                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4060                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4061                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4062                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4063                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4064                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4065                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4066                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4067                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4068                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4069                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4070                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4071                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4072                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4073                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4074                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4075                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4076                 p->fp_Texture_ShadowMapRect      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
4077                 p->fp_Texture_ShadowMapCube      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
4078                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4079                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4080                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4081                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4082                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4083                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4084                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4085                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4086                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4087                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4088                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4089                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4090                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4091                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4092                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4093                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4094                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4095                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4096                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4097                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4098                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4099                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4100                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4101                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4102                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4103                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4104                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4105                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4106                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4107                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4108                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4109                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4110                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4111                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4112                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4113                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4114                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4115                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4116                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4117                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4118                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4119                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4120                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4121                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4122                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4123                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4124                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4125                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4126                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4127                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4128                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4129                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4130                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4131                 CHECKCGERROR
4132         }
4133
4134         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4135                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4136         else
4137                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4138
4139         // free the strings
4140         if (vertstring)
4141                 Mem_Free(vertstring);
4142         if (geomstring)
4143                 Mem_Free(geomstring);
4144         if (fragstring)
4145                 Mem_Free(fragstring);
4146         if (vertexstring)
4147                 Mem_Free(vertexstring);
4148         if (geometrystring)
4149                 Mem_Free(geometrystring);
4150         if (fragmentstring)
4151                 Mem_Free(fragmentstring);
4152 }
4153
4154 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4155 {
4156         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4157         CHECKGLERROR
4158         CHECKCGERROR
4159         if (r_cg_permutation != perm)
4160         {
4161                 r_cg_permutation = perm;
4162                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4163                 {
4164                         if (!r_cg_permutation->compiled)
4165                                 R_CG_CompilePermutation(perm, mode, permutation);
4166                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4167                         {
4168                                 // remove features until we find a valid permutation
4169                                 int i;
4170                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4171                                 {
4172                                         // reduce i more quickly whenever it would not remove any bits
4173                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4174                                         if (!(permutation & j))
4175                                                 continue;
4176                                         permutation -= j;
4177                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4178                                         if (!r_cg_permutation->compiled)
4179                                                 R_CG_CompilePermutation(perm, mode, permutation);
4180                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4181                                                 break;
4182                                 }
4183                                 if (i >= SHADERPERMUTATION_COUNT)
4184                                 {
4185                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4186                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4187                                         return; // no bit left to clear, entire mode is broken
4188                                 }
4189                         }
4190                 }
4191                 CHECKGLERROR
4192                 CHECKCGERROR
4193                 if (r_cg_permutation->vprogram)
4194                 {
4195                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4196                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4197                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4198                 }
4199                 else
4200                 {
4201                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4202                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4203                 }
4204                 if (r_cg_permutation->fprogram)
4205                 {
4206                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4207                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4208                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4209                 }
4210                 else
4211                 {
4212                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4213                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4214                 }
4215         }
4216         CHECKCGERROR
4217         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4218         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4219         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4220 }
4221
4222 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4223 {
4224         cgGLSetTextureParameter(param, R_GetTexture(tex));
4225         cgGLEnableTextureParameter(param);
4226 }
4227 #endif
4228
4229 void R_GLSL_Restart_f(void)
4230 {
4231         unsigned int i, limit;
4232         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4233                 Mem_Free(glslshaderstring);
4234         glslshaderstring = NULL;
4235         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4236                 Mem_Free(cgshaderstring);
4237         cgshaderstring = NULL;
4238         switch(vid.renderpath)
4239         {
4240         case RENDERPATH_GL20:
4241                 {
4242                         r_glsl_permutation_t *p;
4243                         r_glsl_permutation = NULL;
4244                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4245                         for (i = 0;i < limit;i++)
4246                         {
4247                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4248                                 {
4249                                         GL_Backend_FreeProgram(p->program);
4250                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4251                                 }
4252                         }
4253                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4254                 }
4255                 break;
4256         case RENDERPATH_CGGL:
4257 #ifdef SUPPORTCG
4258                 {
4259                         r_cg_permutation_t *p;
4260                         r_cg_permutation = NULL;
4261                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4262                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4263                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4264                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4265                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4266                         for (i = 0;i < limit;i++)
4267                         {
4268                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4269                                 {
4270                                         if (p->vprogram)
4271                                                 cgDestroyProgram(p->vprogram);
4272                                         if (p->fprogram)
4273                                                 cgDestroyProgram(p->fprogram);
4274                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4275                                 }
4276                         }
4277                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4278                 }
4279                 break;
4280 #endif
4281         case RENDERPATH_GL13:
4282         case RENDERPATH_GL11:
4283                 break;
4284         }
4285 }
4286
4287 void R_GLSL_DumpShader_f(void)
4288 {
4289         int i;
4290         qfile_t *file;
4291
4292         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4293         if (file)
4294         {
4295                 FS_Print(file, "/* The engine may define the following macros:\n");
4296                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4297                 for (i = 0;i < SHADERMODE_COUNT;i++)
4298                         FS_Print(file, glslshadermodeinfo[i].pretext);
4299                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4300                         FS_Print(file, shaderpermutationinfo[i].pretext);
4301                 FS_Print(file, "*/\n");
4302                 FS_Print(file, builtinshaderstring);
4303                 FS_Close(file);
4304                 Con_Printf("glsl/default.glsl written\n");
4305         }
4306         else
4307                 Con_Printf("failed to write to glsl/default.glsl\n");
4308
4309 #ifdef SUPPORTCG
4310         file = FS_OpenRealFile("cg/default.cg", "w", false);
4311         if (file)
4312         {
4313                 FS_Print(file, "/* The engine may define the following macros:\n");
4314                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4315                 for (i = 0;i < SHADERMODE_COUNT;i++)
4316                         FS_Print(file, cgshadermodeinfo[i].pretext);
4317                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4318                         FS_Print(file, shaderpermutationinfo[i].pretext);
4319                 FS_Print(file, "*/\n");
4320                 FS_Print(file, builtincgshaderstring);
4321                 FS_Close(file);
4322                 Con_Printf("cg/default.cg written\n");
4323         }
4324         else
4325                 Con_Printf("failed to write to cg/default.cg\n");
4326 #endif
4327 }
4328
4329 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4330 {
4331         if (!second)
4332                 texturemode = GL_MODULATE;
4333         switch (vid.renderpath)
4334         {
4335         case RENDERPATH_GL20:
4336                 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))));
4337                 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
4338                 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, second);
4339                 break;
4340         case RENDERPATH_CGGL:
4341 #ifdef SUPPORTCG
4342                 CHECKCGERROR
4343                 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))));
4344                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4345                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4346 #endif
4347                 break;
4348         case RENDERPATH_GL13:
4349                 R_Mesh_TexBind(0, first );
4350                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4351                 R_Mesh_TexBind(1, second);
4352                 if (second)
4353                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4354                 break;
4355         case RENDERPATH_GL11:
4356                 R_Mesh_TexBind(0, first );
4357                 break;
4358         }
4359 }
4360
4361 void R_SetupShader_DepthOrShadow(void)
4362 {
4363         switch (vid.renderpath)
4364         {
4365         case RENDERPATH_GL20:
4366                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4367                 break;
4368         case RENDERPATH_CGGL:
4369 #ifdef SUPPORTCG
4370                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4371 #endif
4372                 break;
4373         case RENDERPATH_GL13:
4374                 R_Mesh_TexBind(0, 0);
4375                 R_Mesh_TexBind(1, 0);
4376                 break;
4377         case RENDERPATH_GL11:
4378                 R_Mesh_TexBind(0, 0);
4379                 break;
4380         }
4381 }
4382
4383 void R_SetupShader_ShowDepth(void)
4384 {
4385         switch (vid.renderpath)
4386         {
4387         case RENDERPATH_GL20:
4388                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4389                 break;
4390         case RENDERPATH_CGGL:
4391 #ifdef SUPPORTCG
4392                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4393 #endif
4394                 break;
4395         case RENDERPATH_GL13:
4396                 break;
4397         case RENDERPATH_GL11:
4398                 break;
4399         }
4400 }
4401
4402 extern qboolean r_shadow_usingdeferredprepass;
4403 extern cvar_t r_shadow_deferred_8bitrange;
4404 extern rtexture_t *r_shadow_attenuationgradienttexture;
4405 extern rtexture_t *r_shadow_attenuation2dtexture;
4406 extern rtexture_t *r_shadow_attenuation3dtexture;
4407 extern qboolean r_shadow_usingshadowmaprect;
4408 extern qboolean r_shadow_usingshadowmapcube;
4409 extern qboolean r_shadow_usingshadowmap2d;
4410 extern qboolean r_shadow_usingshadowmaportho;
4411 extern float r_shadow_shadowmap_texturescale[2];
4412 extern float r_shadow_shadowmap_parameters[4];
4413 extern qboolean r_shadow_shadowmapvsdct;
4414 extern qboolean r_shadow_shadowmapsampler;
4415 extern int r_shadow_shadowmappcf;
4416 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4417 extern rtexture_t *r_shadow_shadowmap2dtexture;
4418 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4419 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4420 extern matrix4x4_t r_shadow_shadowmapmatrix;
4421 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4422 extern int r_shadow_prepass_width;
4423 extern int r_shadow_prepass_height;
4424 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4425 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4426 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4427 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4428 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
4429 {
4430         // select a permutation of the lighting shader appropriate to this
4431         // combination of texture, entity, light source, and fogging, only use the
4432         // minimum features necessary to avoid wasting rendering time in the
4433         // fragment shader on features that are not being used
4434         unsigned int permutation = 0;
4435         unsigned int mode = 0;
4436         float m16f[16];
4437         if (rsurfacepass == RSURFPASS_BACKGROUND)
4438         {
4439                 // distorted background
4440                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4441                         mode = SHADERMODE_WATER;
4442                 else
4443                         mode = SHADERMODE_REFRACTION;
4444                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4445                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4446                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4447                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4448                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4449                 R_Mesh_ColorPointer(NULL, 0, 0);
4450                 GL_AlphaTest(false);
4451                 GL_BlendFunc(GL_ONE, GL_ZERO);
4452         }
4453         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4454         {
4455                 if (r_glsl_offsetmapping.integer)
4456                 {
4457                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4458                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4459                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4460                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4461                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4462                         {
4463                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4464                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4465                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4466                         }
4467                 }
4468                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4469                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4470                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4471                         permutation |= SHADERPERMUTATION_ALPHAKILL;
4472                 // normalmap (deferred prepass), may use alpha test on diffuse
4473                 mode = SHADERMODE_DEFERREDGEOMETRY;
4474                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4475                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4476                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4477                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4478                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4479                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4480                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4481                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4482                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4483                 else
4484                         R_Mesh_ColorPointer(NULL, 0, 0);
4485                 GL_AlphaTest(false);
4486                 GL_BlendFunc(GL_ONE, GL_ZERO);
4487         }
4488         else if (rsurfacepass == RSURFPASS_RTLIGHT)
4489         {
4490                 if (r_glsl_offsetmapping.integer)
4491                 {
4492                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4493                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4494                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4495                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4496                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4497                         {
4498                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4499                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4500                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4501                         }
4502                 }
4503                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4504                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4505                 // light source
4506                 mode = SHADERMODE_LIGHTSOURCE;
4507                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4508                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4509                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4510                         permutation |= SHADERPERMUTATION_CUBEFILTER;
4511                 if (diffusescale > 0)
4512                         permutation |= SHADERPERMUTATION_DIFFUSE;
4513                 if (specularscale > 0)
4514                 {
4515                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4516                         if (r_shadow_glossexact.integer)
4517                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4518                 }
4519                 if (r_refdef.fogenabled)
4520                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4521                 if (rsurface.texture->colormapping)
4522                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4523                 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4524                 {
4525                         if (r_shadow_usingshadowmaprect)
4526                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4527                         if (r_shadow_usingshadowmap2d)
4528                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4529                         if (r_shadow_usingshadowmapcube)
4530                                 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4531                         else if(r_shadow_shadowmapvsdct)
4532                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4533
4534                         if (r_shadow_shadowmapsampler)
4535                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4536                         if (r_shadow_shadowmappcf > 1)
4537                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4538                         else if (r_shadow_shadowmappcf)
4539                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4540                 }
4541                 if (rsurface.texture->reflectmasktexture)
4542                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4543                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4544                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4545                 {
4546                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4547                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4548                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4549                 }
4550                 else
4551                 {
4552                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4553                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4554                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4555                 }
4556                 //R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4557                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4558                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4559                 else
4560                         R_Mesh_ColorPointer(NULL, 0, 0);
4561                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4562                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4563         }
4564         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4565         {
4566                 if (r_glsl_offsetmapping.integer)
4567                 {
4568                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4569                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4570                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4571                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4572                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4573                         {
4574                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4575                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4576                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4577                         }
4578                 }
4579                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4580                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4581                 // unshaded geometry (fullbright or ambient model lighting)
4582                 mode = SHADERMODE_FLATCOLOR;
4583                 ambientscale = diffusescale = specularscale = 0;
4584                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4585                         permutation |= SHADERPERMUTATION_GLOW;
4586                 if (r_refdef.fogenabled)
4587                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4588                 if (rsurface.texture->colormapping)
4589                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4590                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4591                 {
4592                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4593                         if (r_shadow_usingshadowmaprect)
4594                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4595                         if (r_shadow_usingshadowmap2d)
4596                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4597
4598                         if (r_shadow_shadowmapsampler)
4599                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4600                         if (r_shadow_shadowmappcf > 1)
4601                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4602                         else if (r_shadow_shadowmappcf)
4603                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4604                 }
4605                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4606                         permutation |= SHADERPERMUTATION_REFLECTION;
4607                 if (rsurface.texture->reflectmasktexture)
4608                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4609                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4610                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4611                 {
4612                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4613                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4614                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4615                 }
4616                 else
4617                 {
4618                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4619                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4620                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4621                 }
4622                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4623                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4624                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4625                 else
4626                         R_Mesh_ColorPointer(NULL, 0, 0);
4627                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4628                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4629         }
4630         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4631         {
4632                 if (r_glsl_offsetmapping.integer)
4633                 {
4634                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4635                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4636                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4637                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4638                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4639                         {
4640                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4641                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4642                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4643                         }
4644                 }
4645                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4646                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4647                 // directional model lighting
4648                 mode = SHADERMODE_LIGHTDIRECTION;
4649                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4650                         permutation |= SHADERPERMUTATION_GLOW;
4651                 permutation |= SHADERPERMUTATION_DIFFUSE;
4652                 if (specularscale > 0)
4653                 {
4654                         permutation |= SHADERPERMUTATION_SPECULAR;
4655                         if (r_shadow_glossexact.integer)
4656                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4657                 }
4658                 if (r_refdef.fogenabled)
4659                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4660                 if (rsurface.texture->colormapping)
4661                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4662                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4663                 {
4664                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4665                         if (r_shadow_usingshadowmaprect)
4666                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4667                         if (r_shadow_usingshadowmap2d)
4668                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4669
4670                         if (r_shadow_shadowmapsampler)
4671                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4672                         if (r_shadow_shadowmappcf > 1)
4673                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4674                         else if (r_shadow_shadowmappcf)
4675                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4676                 }
4677                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4678                         permutation |= SHADERPERMUTATION_REFLECTION;
4679                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4680                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4681                 if (rsurface.texture->reflectmasktexture)
4682                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4683                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4684                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4685                 {
4686                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4687                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4688                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4689                 }
4690                 else
4691                 {
4692                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4693                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4694                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4695                 }
4696                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4697                 R_Mesh_ColorPointer(NULL, 0, 0);
4698                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4699                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4700         }
4701         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
4702         {
4703                 if (r_glsl_offsetmapping.integer)
4704                 {
4705                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4706                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4707                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4708                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4709                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4710                         {
4711                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4712                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4713                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4714                         }
4715                 }
4716                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4717                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4718                 // ambient model lighting
4719                 mode = SHADERMODE_LIGHTDIRECTION;
4720                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4721                         permutation |= SHADERPERMUTATION_GLOW;
4722                 if (r_refdef.fogenabled)
4723                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4724                 if (rsurface.texture->colormapping)
4725                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4726                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4727                 {
4728                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4729                         if (r_shadow_usingshadowmaprect)
4730                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4731                         if (r_shadow_usingshadowmap2d)
4732                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4733
4734                         if (r_shadow_shadowmapsampler)
4735                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4736                         if (r_shadow_shadowmappcf > 1)
4737                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4738                         else if (r_shadow_shadowmappcf)
4739                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4740                 }
4741                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4742                         permutation |= SHADERPERMUTATION_REFLECTION;
4743                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4744                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4745                 if (rsurface.texture->reflectmasktexture)
4746                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4747                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4748                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4749                 {
4750                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4751                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4752                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4753                 }
4754                 else
4755                 {
4756                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4757                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4758                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4759                 }
4760                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4761                 R_Mesh_ColorPointer(NULL, 0, 0);
4762                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4763                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4764         }
4765         else
4766         {
4767                 if (r_glsl_offsetmapping.integer)
4768                 {
4769                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4770                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4771                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4772                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4773                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4774                         {
4775                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4776                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4777                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4778                         }
4779                 }
4780                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4781                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4782                 // lightmapped wall
4783                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4784                         permutation |= SHADERPERMUTATION_GLOW;
4785                 if (r_refdef.fogenabled)
4786                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4787                 if (rsurface.texture->colormapping)
4788                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4789                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4790                 {
4791                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4792                         if (r_shadow_usingshadowmaprect)
4793                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4794                         if (r_shadow_usingshadowmap2d)
4795                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4796
4797                         if (r_shadow_shadowmapsampler)
4798                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4799                         if (r_shadow_shadowmappcf > 1)
4800                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4801                         else if (r_shadow_shadowmappcf)
4802                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4803                 }
4804                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4805                         permutation |= SHADERPERMUTATION_REFLECTION;
4806                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4807                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4808                 if (rsurface.texture->reflectmasktexture)
4809                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4810                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
4811                 {
4812                         // deluxemapping (light direction texture)
4813                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
4814                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
4815                         else
4816                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4817                         permutation |= SHADERPERMUTATION_DIFFUSE;
4818                         if (specularscale > 0)
4819                         {
4820                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4821                                 if (r_shadow_glossexact.integer)
4822                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4823                         }
4824                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4825                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4826                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4827                         else
4828                                 R_Mesh_ColorPointer(NULL, 0, 0);
4829                 }
4830                 else if (r_glsl_deluxemapping.integer >= 2)
4831                 {
4832                         // fake deluxemapping (uniform light direction in tangentspace)
4833                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4834                         permutation |= SHADERPERMUTATION_DIFFUSE;
4835                         if (specularscale > 0)
4836                         {
4837                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4838                                 if (r_shadow_glossexact.integer)
4839                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4840                         }
4841                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4842                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4843                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4844                         else
4845                                 R_Mesh_ColorPointer(NULL, 0, 0);
4846                 }
4847                 else if (rsurface.uselightmaptexture)
4848                 {
4849                         // ordinary lightmapping (q1bsp, q3bsp)
4850                         mode = SHADERMODE_LIGHTMAP;
4851                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4852                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4853                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4854                         else
4855                                 R_Mesh_ColorPointer(NULL, 0, 0);
4856                 }
4857                 else
4858                 {
4859                         // ordinary vertex coloring (q3bsp)
4860                         mode = SHADERMODE_VERTEXCOLOR;
4861                         R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4862                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4863                 }
4864                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4865                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4866                 {
4867                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4868                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4869                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4870                 }
4871                 else
4872                 {
4873                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4874                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4875                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4876                 }
4877                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4878                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4879         }
4880         switch(vid.renderpath)
4881         {
4882         case RENDERPATH_GL20:
4883                 R_SetupShader_SetPermutationGLSL(mode, permutation);
4884                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
4885                 if (mode == SHADERMODE_LIGHTSOURCE)
4886                 {
4887                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
4888                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
4889                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
4890                         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);
4891                         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);
4892                         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);
4893         
4894                         // additive passes are only darkened by fog, not tinted
4895                         if (r_glsl_permutation->loc_FogColor >= 0)
4896                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4897                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4898                 }
4899                 else
4900                 {
4901                         if (mode == SHADERMODE_FLATCOLOR)
4902                         {
4903                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
4904                         }
4905                         else if (mode == SHADERMODE_LIGHTDIRECTION)
4906                         {
4907                                 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]);
4908                                 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]);
4909                                 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);
4910                                 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);
4911                                 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);
4912                                 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]);
4913                                 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]);
4914                         }
4915                         else
4916                         {
4917                                 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]);
4918                                 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]);
4919                                 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);
4920                                 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);
4921                                 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);
4922                         }
4923                         // additive passes are only darkened by fog, not tinted
4924                         if (r_glsl_permutation->loc_FogColor >= 0)
4925                         {
4926                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4927                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4928                                 else
4929                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4930                         }
4931                         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);
4932                         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]);
4933                         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]);
4934                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
4935                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
4936                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
4937                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
4938                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4939                 }
4940                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
4941                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
4942                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
4943                 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]);
4944                 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]);
4945
4946                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
4947                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
4948                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
4949                 if (r_glsl_permutation->loc_Color_Pants >= 0)
4950                 {
4951                         if (rsurface.texture->pantstexture)
4952                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4953                         else
4954                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
4955                 }
4956                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
4957                 {
4958                         if (rsurface.texture->shirttexture)
4959                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4960                         else
4961                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
4962                 }
4963                 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]);
4964                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
4965                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
4966                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
4967                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
4968                 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]);
4969                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
4970
4971         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
4972         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
4973         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
4974                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
4975                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
4976                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
4977                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
4978                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
4979                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
4980                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
4981                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
4982                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
4983                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
4984                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
4985                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
4986                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
4987                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_white                                     );
4988                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_blanknormalmap                            );
4989                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
4990                 if (r_glsl_permutation->loc_Texture_Refraction      >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , r_texture_white                                     );
4991                 if (r_glsl_permutation->loc_Texture_Reflection      >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , r_texture_white                                     );
4992                 if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
4993                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
4994                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
4995                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
4996                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
4997                 {
4998                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
4999                         if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT, r_shadow_shadowmaprectangletexture                  );
5000                         if (rsurface.rtlight)
5001                         {
5002                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5003                                 if (r_shadow_usingshadowmapcube)
5004                                         if (r_glsl_permutation->loc_Texture_ShadowMapCube   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE     , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5005                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5006                         }
5007                 }
5008                 CHECKGLERROR
5009                 break;
5010         case RENDERPATH_CGGL:
5011 #ifdef SUPPORTCG
5012                 R_SetupShader_SetPermutationCG(mode, permutation);
5013                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
5014                 if (mode == SHADERMODE_LIGHTSOURCE)
5015                 {
5016                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
5017                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5018                 }
5019                 else
5020                 {
5021                         if (mode == SHADERMODE_LIGHTDIRECTION)
5022                         {
5023                                 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
5024                         }
5025                 }
5026                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
5027                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
5028                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
5029                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5030                 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
5031                 CHECKGLERROR
5032
5033                 if (mode == SHADERMODE_LIGHTSOURCE)
5034                 {
5035                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5036                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
5037                         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
5038                         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
5039                         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
5040
5041                         // additive passes are only darkened by fog, not tinted
5042                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
5043                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5044                 }
5045                 else
5046                 {
5047                         if (mode == SHADERMODE_FLATCOLOR)
5048                         {
5049                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);CHECKCGERROR
5050                         }
5051                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5052                         {
5053                                 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
5054                                 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
5055                                 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
5056                                 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
5057                                 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
5058                                 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
5059                                 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
5060                         }
5061                         else
5062                         {
5063                                 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
5064                                 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
5065                                 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
5066                                 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
5067                                 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
5068                         }
5069                         // additive passes are only darkened by fog, not tinted
5070                         if (r_cg_permutation->fp_FogColor)
5071                         {
5072                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5073                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
5074                                 else
5075                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5076                                 CHECKCGERROR
5077                         }
5078                         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
5079                         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
5080                         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
5081                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
5082                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
5083                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
5084                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
5085                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5086                 }
5087                 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
5088                 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
5089                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
5090                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
5091                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5092                 if (r_cg_permutation->fp_Color_Pants)
5093                 {
5094                         if (rsurface.texture->pantstexture)
5095                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5096                         else
5097                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
5098                         CHECKCGERROR
5099                 }
5100                 if (r_cg_permutation->fp_Color_Shirt)
5101                 {
5102                         if (rsurface.texture->shirttexture)
5103                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5104                         else
5105                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
5106                         CHECKCGERROR
5107                 }
5108                 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
5109                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
5110                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
5111                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
5112                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
5113                 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
5114                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5115
5116         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
5117         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
5118         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
5119                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
5120                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
5121                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
5122                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
5123                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
5124                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
5125                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
5126                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
5127                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
5128                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
5129                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
5130                 if (r_cg_permutation->fp_Texture_ReflectCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectCube    , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);CHECKCGERROR
5131                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
5132                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , r_texture_white                                     );CHECKCGERROR
5133                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , r_texture_blanknormalmap                            );CHECKCGERROR
5134                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
5135                 if (r_cg_permutation->fp_Texture_Refraction     ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction     , r_texture_white                                     );CHECKCGERROR
5136                 if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , r_texture_white                                     );CHECKCGERROR
5137                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
5138                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
5139                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
5140                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
5141                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5142                 {
5143                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5144                         if (r_cg_permutation->fp_Texture_ShadowMapRect  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
5145                         if (rsurface.rtlight)
5146                         {
5147                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
5148                                 if (r_shadow_usingshadowmapcube)
5149                                         if (r_cg_permutation->fp_Texture_ShadowMapCube  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5150                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
5151                         }
5152                 }
5153
5154                 CHECKGLERROR
5155 #endif
5156                 break;
5157         case RENDERPATH_GL13:
5158         case RENDERPATH_GL11:
5159                 break;
5160         }
5161 }
5162
5163 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
5164 {
5165         // select a permutation of the lighting shader appropriate to this
5166         // combination of texture, entity, light source, and fogging, only use the
5167         // minimum features necessary to avoid wasting rendering time in the
5168         // fragment shader on features that are not being used
5169         unsigned int permutation = 0;
5170         unsigned int mode = 0;
5171         const float *lightcolorbase = rtlight->currentcolor;
5172         float ambientscale = rtlight->ambientscale;
5173         float diffusescale = rtlight->diffusescale;
5174         float specularscale = rtlight->specularscale;
5175         // this is the location of the light in view space
5176         vec3_t viewlightorigin;
5177         // this transforms from view space (camera) to light space (cubemap)
5178         matrix4x4_t viewtolight;
5179         matrix4x4_t lighttoview;
5180         float viewtolight16f[16];
5181         float range = 1.0f / r_shadow_deferred_8bitrange.value;
5182         // light source
5183         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
5184         if (rtlight->currentcubemap != r_texture_whitecube)
5185                 permutation |= SHADERPERMUTATION_CUBEFILTER;
5186         if (diffusescale > 0)
5187                 permutation |= SHADERPERMUTATION_DIFFUSE;
5188         if (specularscale > 0)
5189         {
5190                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5191                 if (r_shadow_glossexact.integer)
5192                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5193         }
5194         if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
5195         {
5196                 if (r_shadow_usingshadowmaprect)
5197                         permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5198                 if (r_shadow_usingshadowmap2d)
5199                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5200                 if (r_shadow_usingshadowmapcube)
5201                         permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
5202                 else if(r_shadow_shadowmapvsdct)
5203                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5204
5205                 if (r_shadow_shadowmapsampler)
5206                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5207                 if (r_shadow_shadowmappcf > 1)
5208                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5209                 else if (r_shadow_shadowmappcf)
5210                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5211         }
5212         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
5213         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
5214         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
5215         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
5216         switch(vid.renderpath)
5217         {
5218         case RENDERPATH_GL20:
5219                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5220                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5221                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
5222                 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);
5223                 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);
5224                 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);
5225                 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]);
5226                 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]);
5227                 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));
5228                 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]);
5229                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5230
5231                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
5232                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
5233                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
5234                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
5235                 if (r_glsl_permutation->loc_Texture_ShadowMapRect     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT      , r_shadow_shadowmaprectangletexture                  );
5236                 if (r_shadow_usingshadowmapcube)
5237                         if (r_glsl_permutation->loc_Texture_ShadowMapCube     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE      , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5238                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
5239                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
5240                 break;
5241         case RENDERPATH_CGGL:
5242 #ifdef SUPPORTCG
5243                 R_SetupShader_SetPermutationCG(mode, permutation);
5244                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
5245                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
5246                 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
5247                 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
5248                 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
5249                 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
5250                 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
5251                 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
5252                 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
5253                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5254
5255                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
5256                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
5257                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
5258                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
5259                 if (r_cg_permutation->fp_Texture_ShadowMapRect    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
5260                 if (r_shadow_usingshadowmapcube)
5261                         if (r_cg_permutation->fp_Texture_ShadowMapCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5262                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5263                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
5264 #endif
5265                 break;
5266         case RENDERPATH_GL13:
5267         case RENDERPATH_GL11:
5268                 break;
5269         }
5270 }
5271
5272 #define SKINFRAME_HASH 1024
5273
5274 typedef struct
5275 {
5276         int loadsequence; // incremented each level change
5277         memexpandablearray_t array;
5278         skinframe_t *hash[SKINFRAME_HASH];
5279 }
5280 r_skinframe_t;
5281 r_skinframe_t r_skinframe;
5282
5283 void R_SkinFrame_PrepareForPurge(void)
5284 {
5285         r_skinframe.loadsequence++;
5286         // wrap it without hitting zero
5287         if (r_skinframe.loadsequence >= 200)
5288                 r_skinframe.loadsequence = 1;
5289 }
5290
5291 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5292 {
5293         if (!skinframe)
5294                 return;
5295         // mark the skinframe as used for the purging code
5296         skinframe->loadsequence = r_skinframe.loadsequence;
5297 }
5298
5299 void R_SkinFrame_Purge(void)
5300 {
5301         int i;
5302         skinframe_t *s;
5303         for (i = 0;i < SKINFRAME_HASH;i++)
5304         {
5305                 for (s = r_skinframe.hash[i];s;s = s->next)
5306                 {
5307                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5308                         {
5309                                 if (s->merged == s->base)
5310                                         s->merged = NULL;
5311                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5312                                 R_PurgeTexture(s->stain );s->stain  = NULL;
5313                                 R_PurgeTexture(s->merged);s->merged = NULL;
5314                                 R_PurgeTexture(s->base  );s->base   = NULL;
5315                                 R_PurgeTexture(s->pants );s->pants  = NULL;
5316                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
5317                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
5318                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
5319                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
5320                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
5321                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
5322                                 s->loadsequence = 0;
5323                         }
5324                 }
5325         }
5326 }
5327
5328 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5329         skinframe_t *item;
5330         char basename[MAX_QPATH];
5331
5332         Image_StripImageExtension(name, basename, sizeof(basename));
5333
5334         if( last == NULL ) {
5335                 int hashindex;
5336                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5337                 item = r_skinframe.hash[hashindex];
5338         } else {
5339                 item = last->next;
5340         }
5341
5342         // linearly search through the hash bucket
5343         for( ; item ; item = item->next ) {
5344                 if( !strcmp( item->basename, basename ) ) {
5345                         return item;
5346                 }
5347         }
5348         return NULL;
5349 }
5350
5351 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5352 {
5353         skinframe_t *item;
5354         int hashindex;
5355         char basename[MAX_QPATH];
5356
5357         Image_StripImageExtension(name, basename, sizeof(basename));
5358
5359         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5360         for (item = r_skinframe.hash[hashindex];item;item = item->next)
5361                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5362                         break;
5363
5364         if (!item) {
5365                 rtexture_t *dyntexture;
5366                 // check whether its a dynamic texture
5367                 dyntexture = CL_GetDynTexture( basename );
5368                 if (!add && !dyntexture)
5369                         return NULL;
5370                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5371                 memset(item, 0, sizeof(*item));
5372                 strlcpy(item->basename, basename, sizeof(item->basename));
5373                 item->base = dyntexture; // either NULL or dyntexture handle
5374                 item->textureflags = textureflags;
5375                 item->comparewidth = comparewidth;
5376                 item->compareheight = compareheight;
5377                 item->comparecrc = comparecrc;
5378                 item->next = r_skinframe.hash[hashindex];
5379                 r_skinframe.hash[hashindex] = item;
5380         }
5381         else if( item->base == NULL )
5382         {
5383                 rtexture_t *dyntexture;
5384                 // check whether its a dynamic texture
5385                 // 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]
5386                 dyntexture = CL_GetDynTexture( basename );
5387                 item->base = dyntexture; // either NULL or dyntexture handle
5388         }
5389
5390         R_SkinFrame_MarkUsed(item);
5391         return item;
5392 }
5393
5394 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5395         { \
5396                 unsigned long long avgcolor[5], wsum; \
5397                 int pix, comp, w; \
5398                 avgcolor[0] = 0; \
5399                 avgcolor[1] = 0; \
5400                 avgcolor[2] = 0; \
5401                 avgcolor[3] = 0; \
5402                 avgcolor[4] = 0; \
5403                 wsum = 0; \
5404                 for(pix = 0; pix < cnt; ++pix) \
5405                 { \
5406                         w = 0; \
5407                         for(comp = 0; comp < 3; ++comp) \
5408                                 w += getpixel; \
5409                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5410                         { \
5411                                 ++wsum; \
5412                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5413                                 w = getpixel; \
5414                                 for(comp = 0; comp < 3; ++comp) \
5415                                         avgcolor[comp] += getpixel * w; \
5416                                 avgcolor[3] += w; \
5417                         } \
5418                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5419                         avgcolor[4] += getpixel; \
5420                 } \
5421                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5422                         avgcolor[3] = 1; \
5423                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5424                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5425                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5426                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5427         }
5428
5429 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5430 {
5431         int j;
5432         unsigned char *pixels;
5433         unsigned char *bumppixels;
5434         unsigned char *basepixels = NULL;
5435         int basepixels_width = 0;
5436         int basepixels_height = 0;
5437         skinframe_t *skinframe;
5438         rtexture_t *ddsbase = NULL;
5439         qboolean ddshasalpha = false;
5440         float ddsavgcolor[4];
5441         char basename[MAX_QPATH];
5442
5443         if (cls.state == ca_dedicated)
5444                 return NULL;
5445
5446         // return an existing skinframe if already loaded
5447         // if loading of the first image fails, don't make a new skinframe as it
5448         // would cause all future lookups of this to be missing
5449         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5450         if (skinframe && skinframe->base)
5451                 return skinframe;
5452
5453         Image_StripImageExtension(name, basename, sizeof(basename));
5454
5455         // check for DDS texture file first
5456         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor)))
5457         {
5458                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer);
5459                 if (basepixels == NULL)
5460                         return NULL;
5461         }
5462
5463         if (developer_loading.integer)
5464                 Con_Printf("loading skin \"%s\"\n", name);
5465
5466         // we've got some pixels to store, so really allocate this new texture now
5467         if (!skinframe)
5468                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5469         skinframe->stain = NULL;
5470         skinframe->merged = NULL;
5471         skinframe->base = NULL;
5472         skinframe->pants = NULL;
5473         skinframe->shirt = NULL;
5474         skinframe->nmap = NULL;
5475         skinframe->gloss = NULL;
5476         skinframe->glow = NULL;
5477         skinframe->fog = NULL;
5478         skinframe->reflect = NULL;
5479         skinframe->hasalpha = false;
5480
5481         if (ddsbase)
5482         {
5483                 skinframe->base = ddsbase;
5484                 skinframe->hasalpha = ddshasalpha;
5485                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5486                 if (r_loadfog && skinframe->hasalpha)
5487                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5488                 //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]);
5489         }
5490         else
5491         {
5492                 basepixels_width = image_width;
5493                 basepixels_height = image_height;
5494                 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);
5495                 if (textureflags & TEXF_ALPHA)
5496                 {
5497                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5498                         {
5499                                 if (basepixels[j] < 255)
5500                                 {
5501                                         skinframe->hasalpha = true;
5502                                         break;
5503                                 }
5504                         }
5505                         if (r_loadfog && skinframe->hasalpha)
5506                         {
5507                                 // has transparent pixels
5508                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5509                                 for (j = 0;j < image_width * image_height * 4;j += 4)
5510                                 {
5511                                         pixels[j+0] = 255;
5512                                         pixels[j+1] = 255;
5513                                         pixels[j+2] = 255;
5514                                         pixels[j+3] = basepixels[j+3];
5515                                 }
5516                                 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);
5517                                 Mem_Free(pixels);
5518                         }
5519                 }
5520                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5521                 //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]);
5522                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5523                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true);
5524                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
5525                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true);
5526         }
5527
5528         if (r_loaddds)
5529         {
5530                 if (r_loadnormalmap)
5531                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5532                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL);
5533                 if (r_loadgloss)
5534                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL);
5535                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL);
5536                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL);
5537                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL);
5538         }
5539
5540         // _norm is the name used by tenebrae and has been adopted as standard
5541         if (r_loadnormalmap && skinframe->nmap == NULL)
5542         {
5543                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false)) != NULL)
5544                 {
5545                         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);
5546                         Mem_Free(pixels);
5547                         pixels = NULL;
5548                 }
5549                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false)) != NULL)
5550                 {
5551                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5552                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5553                         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);
5554                         Mem_Free(pixels);
5555                         Mem_Free(bumppixels);
5556                 }
5557                 else if (r_shadow_bumpscale_basetexture.value > 0)
5558                 {
5559                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5560                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5561                         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);
5562                         Mem_Free(pixels);
5563                 }
5564                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
5565                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true);
5566         }
5567
5568         // _luma is supported only for tenebrae compatibility
5569         // _glow is the preferred name
5570         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer))))
5571         {
5572                 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);
5573                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
5574                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true);
5575                 Mem_Free(pixels);pixels = NULL;
5576         }
5577
5578         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5579         {
5580                 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);
5581                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
5582                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true);
5583                 Mem_Free(pixels);
5584                 pixels = NULL;
5585         }
5586
5587         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5588         {
5589                 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);
5590                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
5591                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true);
5592                 Mem_Free(pixels);
5593                 pixels = NULL;
5594         }
5595
5596         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5597         {
5598                 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);
5599                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
5600                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true);
5601                 Mem_Free(pixels);
5602                 pixels = NULL;
5603         }
5604
5605         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5606         {
5607                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), NULL);
5608                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
5609                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true);
5610                 Mem_Free(pixels);
5611                 pixels = NULL;
5612         }
5613
5614         if (basepixels)
5615                 Mem_Free(basepixels);
5616
5617         return skinframe;
5618 }
5619
5620 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
5621 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
5622 {
5623         int i;
5624         unsigned char *temp1, *temp2;
5625         skinframe_t *skinframe;
5626
5627         if (cls.state == ca_dedicated)
5628                 return NULL;
5629
5630         // if already loaded just return it, otherwise make a new skinframe
5631         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
5632         if (skinframe && skinframe->base)
5633                 return skinframe;
5634
5635         skinframe->stain = NULL;
5636         skinframe->merged = NULL;
5637         skinframe->base = NULL;
5638         skinframe->pants = NULL;
5639         skinframe->shirt = NULL;
5640         skinframe->nmap = NULL;
5641         skinframe->gloss = NULL;
5642         skinframe->glow = NULL;
5643         skinframe->fog = NULL;
5644         skinframe->reflect = NULL;
5645         skinframe->hasalpha = false;
5646
5647         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5648         if (!skindata)
5649                 return NULL;
5650
5651         if (developer_loading.integer)
5652                 Con_Printf("loading 32bit skin \"%s\"\n", name);
5653
5654         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
5655         {
5656                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5657                 temp2 = temp1 + width * height * 4;
5658                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5659                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5660                 Mem_Free(temp1);
5661         }
5662         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5663         if (textureflags & TEXF_ALPHA)
5664         {
5665                 for (i = 3;i < width * height * 4;i += 4)
5666                 {
5667                         if (skindata[i] < 255)
5668                         {
5669                                 skinframe->hasalpha = true;
5670                                 break;
5671                         }
5672                 }
5673                 if (r_loadfog && skinframe->hasalpha)
5674                 {
5675                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
5676                         memcpy(fogpixels, skindata, width * height * 4);
5677                         for (i = 0;i < width * height * 4;i += 4)
5678                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
5679                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5680                         Mem_Free(fogpixels);
5681                 }
5682         }
5683
5684         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
5685         //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]);
5686
5687         return skinframe;
5688 }
5689
5690 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
5691 {
5692         int i;
5693         int featuresmask;
5694         skinframe_t *skinframe;
5695
5696         if (cls.state == ca_dedicated)
5697                 return NULL;
5698
5699         // if already loaded just return it, otherwise make a new skinframe
5700         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5701         if (skinframe && skinframe->base)
5702                 return skinframe;
5703
5704         skinframe->stain = NULL;
5705         skinframe->merged = NULL;
5706         skinframe->base = NULL;
5707         skinframe->pants = NULL;
5708         skinframe->shirt = NULL;
5709         skinframe->nmap = NULL;
5710         skinframe->gloss = NULL;
5711         skinframe->glow = NULL;
5712         skinframe->fog = NULL;
5713         skinframe->reflect = NULL;
5714         skinframe->hasalpha = false;
5715
5716         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5717         if (!skindata)
5718                 return NULL;
5719
5720         if (developer_loading.integer)
5721                 Con_Printf("loading quake skin \"%s\"\n", name);
5722
5723         // 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)
5724         skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
5725         memcpy(skinframe->qpixels, skindata, width*height);
5726         skinframe->qwidth = width;
5727         skinframe->qheight = height;
5728
5729         featuresmask = 0;
5730         for (i = 0;i < width * height;i++)
5731                 featuresmask |= palette_featureflags[skindata[i]];
5732
5733         skinframe->hasalpha = false;
5734         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
5735         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
5736         skinframe->qgeneratemerged = true;
5737         skinframe->qgeneratebase = skinframe->qhascolormapping;
5738         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
5739
5740         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
5741         //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]);
5742
5743         return skinframe;
5744 }
5745
5746 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
5747 {
5748         int width;
5749         int height;
5750         unsigned char *skindata;
5751
5752         if (!skinframe->qpixels)
5753                 return;
5754
5755         if (!skinframe->qhascolormapping)
5756                 colormapped = false;
5757
5758         if (colormapped)
5759         {
5760                 if (!skinframe->qgeneratebase)
5761                         return;
5762         }
5763         else
5764         {
5765                 if (!skinframe->qgeneratemerged)
5766                         return;
5767         }
5768
5769         width = skinframe->qwidth;
5770         height = skinframe->qheight;
5771         skindata = skinframe->qpixels;
5772
5773         if (skinframe->qgeneratenmap)
5774         {
5775                 unsigned char *temp1, *temp2;
5776                 skinframe->qgeneratenmap = false;
5777                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5778                 temp2 = temp1 + width * height * 4;
5779                 // use either a custom palette or the quake palette
5780                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
5781                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5782                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5783                 Mem_Free(temp1);
5784         }
5785
5786         if (skinframe->qgenerateglow)
5787         {
5788                 skinframe->qgenerateglow = false;
5789                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
5790         }
5791
5792         if (colormapped)
5793         {
5794                 skinframe->qgeneratebase = false;
5795                 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);
5796                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
5797                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
5798         }
5799         else
5800         {
5801                 skinframe->qgeneratemerged = false;
5802                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
5803         }
5804
5805         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
5806         {
5807                 Mem_Free(skinframe->qpixels);
5808                 skinframe->qpixels = NULL;
5809         }
5810 }
5811
5812 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)
5813 {
5814         int i;
5815         skinframe_t *skinframe;
5816
5817         if (cls.state == ca_dedicated)
5818                 return NULL;
5819
5820         // if already loaded just return it, otherwise make a new skinframe
5821         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5822         if (skinframe && skinframe->base)
5823                 return skinframe;
5824
5825         skinframe->stain = NULL;
5826         skinframe->merged = NULL;
5827         skinframe->base = NULL;
5828         skinframe->pants = NULL;
5829         skinframe->shirt = NULL;
5830         skinframe->nmap = NULL;
5831         skinframe->gloss = NULL;
5832         skinframe->glow = NULL;
5833         skinframe->fog = NULL;
5834         skinframe->reflect = NULL;
5835         skinframe->hasalpha = false;
5836
5837         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5838         if (!skindata)
5839                 return NULL;
5840
5841         if (developer_loading.integer)
5842                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
5843
5844         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
5845         if (textureflags & TEXF_ALPHA)
5846         {
5847                 for (i = 0;i < width * height;i++)
5848                 {
5849                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
5850                         {
5851                                 skinframe->hasalpha = true;
5852                                 break;
5853                         }
5854                 }
5855                 if (r_loadfog && skinframe->hasalpha)
5856                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
5857         }
5858
5859         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
5860         //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]);
5861
5862         return skinframe;
5863 }
5864
5865 skinframe_t *R_SkinFrame_LoadMissing(void)
5866 {
5867         skinframe_t *skinframe;
5868
5869         if (cls.state == ca_dedicated)
5870                 return NULL;
5871
5872         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
5873         skinframe->stain = NULL;
5874         skinframe->merged = NULL;
5875         skinframe->base = NULL;
5876         skinframe->pants = NULL;
5877         skinframe->shirt = NULL;
5878         skinframe->nmap = NULL;
5879         skinframe->gloss = NULL;
5880         skinframe->glow = NULL;
5881         skinframe->fog = NULL;
5882         skinframe->reflect = NULL;
5883         skinframe->hasalpha = false;
5884
5885         skinframe->avgcolor[0] = rand() / RAND_MAX;
5886         skinframe->avgcolor[1] = rand() / RAND_MAX;
5887         skinframe->avgcolor[2] = rand() / RAND_MAX;
5888         skinframe->avgcolor[3] = 1;
5889
5890         return skinframe;
5891 }
5892
5893 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
5894 typedef struct suffixinfo_s
5895 {
5896         char *suffix;
5897         qboolean flipx, flipy, flipdiagonal;
5898 }
5899 suffixinfo_t;
5900 static suffixinfo_t suffix[3][6] =
5901 {
5902         {
5903                 {"px",   false, false, false},
5904                 {"nx",   false, false, false},
5905                 {"py",   false, false, false},
5906                 {"ny",   false, false, false},
5907                 {"pz",   false, false, false},
5908                 {"nz",   false, false, false}
5909         },
5910         {
5911                 {"posx", false, false, false},
5912                 {"negx", false, false, false},
5913                 {"posy", false, false, false},
5914                 {"negy", false, false, false},
5915                 {"posz", false, false, false},
5916                 {"negz", false, false, false}
5917         },
5918         {
5919                 {"rt",    true, false,  true},
5920                 {"lf",   false,  true,  true},
5921                 {"ft",    true,  true, false},
5922                 {"bk",   false, false, false},
5923                 {"up",    true, false,  true},
5924                 {"dn",    true, false,  true}
5925         }
5926 };
5927
5928 static int componentorder[4] = {0, 1, 2, 3};
5929
5930 rtexture_t *R_LoadCubemap(const char *basename)
5931 {
5932         int i, j, cubemapsize;
5933         unsigned char *cubemappixels, *image_buffer;
5934         rtexture_t *cubemaptexture;
5935         char name[256];
5936         // must start 0 so the first loadimagepixels has no requested width/height
5937         cubemapsize = 0;
5938         cubemappixels = NULL;
5939         cubemaptexture = NULL;
5940         // keep trying different suffix groups (posx, px, rt) until one loads
5941         for (j = 0;j < 3 && !cubemappixels;j++)
5942         {
5943                 // load the 6 images in the suffix group
5944                 for (i = 0;i < 6;i++)
5945                 {
5946                         // generate an image name based on the base and and suffix
5947                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
5948                         // load it
5949                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer)))
5950                         {
5951                                 // an image loaded, make sure width and height are equal
5952                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
5953                                 {
5954                                         // if this is the first image to load successfully, allocate the cubemap memory
5955                                         if (!cubemappixels && image_width >= 1)
5956                                         {
5957                                                 cubemapsize = image_width;
5958                                                 // note this clears to black, so unavailable sides are black
5959                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
5960                                         }
5961                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
5962                                         if (cubemappixels)
5963                                                 Image_CopyMux(cubemappixels+i*cubemapsize*cubemapsize*4, image_buffer, cubemapsize, cubemapsize, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, componentorder);
5964                                 }
5965                                 else
5966                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
5967                                 // free the image
5968                                 Mem_Free(image_buffer);
5969                         }
5970                 }
5971         }
5972         // if a cubemap loaded, upload it
5973         if (cubemappixels)
5974         {
5975                 if (developer_loading.integer)
5976                         Con_Printf("loading cubemap \"%s\"\n", basename);
5977
5978                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR, NULL);
5979                 Mem_Free(cubemappixels);
5980         }
5981         else
5982         {
5983                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
5984                 if (developer_loading.integer)
5985                 {
5986                         Con_Printf("(tried tried images ");
5987                         for (j = 0;j < 3;j++)
5988                                 for (i = 0;i < 6;i++)
5989                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
5990                         Con_Print(" and was unable to find any of them).\n");
5991                 }
5992         }
5993         return cubemaptexture;
5994 }
5995
5996 rtexture_t *R_GetCubemap(const char *basename)
5997 {
5998         int i;
5999         for (i = 0;i < r_texture_numcubemaps;i++)
6000                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6001                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6002         if (i >= MAX_CUBEMAPS)
6003                 return r_texture_whitecube;
6004         r_texture_numcubemaps++;
6005         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6006         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6007         return r_texture_cubemaps[i].texture;
6008 }
6009
6010 void R_FreeCubemaps(void)
6011 {
6012         int i;
6013         for (i = 0;i < r_texture_numcubemaps;i++)
6014         {
6015                 if (developer_loading.integer)
6016                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6017                 if (r_texture_cubemaps[i].texture)
6018                         R_FreeTexture(r_texture_cubemaps[i].texture);
6019         }
6020         r_texture_numcubemaps = 0;
6021 }
6022
6023 void R_Main_FreeViewCache(void)
6024 {
6025         if (r_refdef.viewcache.entityvisible)
6026                 Mem_Free(r_refdef.viewcache.entityvisible);
6027         if (r_refdef.viewcache.world_pvsbits)
6028                 Mem_Free(r_refdef.viewcache.world_pvsbits);
6029         if (r_refdef.viewcache.world_leafvisible)
6030                 Mem_Free(r_refdef.viewcache.world_leafvisible);
6031         if (r_refdef.viewcache.world_surfacevisible)
6032                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6033         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6034 }
6035
6036 void R_Main_ResizeViewCache(void)
6037 {
6038         int numentities = r_refdef.scene.numentities;
6039         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6040         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6041         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6042         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6043         if (r_refdef.viewcache.maxentities < numentities)
6044         {
6045                 r_refdef.viewcache.maxentities = numentities;
6046                 if (r_refdef.viewcache.entityvisible)
6047                         Mem_Free(r_refdef.viewcache.entityvisible);
6048                 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6049         }
6050         if (r_refdef.viewcache.world_numclusters != numclusters)
6051         {
6052                 r_refdef.viewcache.world_numclusters = numclusters;
6053                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6054                 if (r_refdef.viewcache.world_pvsbits)
6055                         Mem_Free(r_refdef.viewcache.world_pvsbits);
6056                 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6057         }
6058         if (r_refdef.viewcache.world_numleafs != numleafs)
6059         {
6060                 r_refdef.viewcache.world_numleafs = numleafs;
6061                 if (r_refdef.viewcache.world_leafvisible)
6062                         Mem_Free(r_refdef.viewcache.world_leafvisible);
6063                 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6064         }
6065         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6066         {
6067                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6068                 if (r_refdef.viewcache.world_surfacevisible)
6069                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
6070                 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6071         }
6072 }
6073
6074 extern rtexture_t *loadingscreentexture;
6075 void gl_main_start(void)
6076 {
6077         loadingscreentexture = NULL;
6078         r_texture_blanknormalmap = NULL;
6079         r_texture_white = NULL;
6080         r_texture_grey128 = NULL;
6081         r_texture_black = NULL;
6082         r_texture_whitecube = NULL;
6083         r_texture_normalizationcube = NULL;
6084         r_texture_fogattenuation = NULL;
6085         r_texture_gammaramps = NULL;
6086         r_texture_numcubemaps = 0;
6087
6088         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
6089         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6090
6091         switch(vid.renderpath)
6092         {
6093         case RENDERPATH_GL20:
6094         case RENDERPATH_CGGL:
6095                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6096                 Cvar_SetValueQuick(&gl_combine, 1);
6097                 Cvar_SetValueQuick(&r_glsl, 1);
6098                 r_loadnormalmap = true;
6099                 r_loadgloss = true;
6100                 r_loadfog = false;
6101                 break;
6102         case RENDERPATH_GL13:
6103                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6104                 Cvar_SetValueQuick(&gl_combine, 1);
6105                 Cvar_SetValueQuick(&r_glsl, 0);
6106                 r_loadnormalmap = false;
6107                 r_loadgloss = false;
6108                 r_loadfog = true;
6109                 break;
6110         case RENDERPATH_GL11:
6111                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6112                 Cvar_SetValueQuick(&gl_combine, 0);
6113                 Cvar_SetValueQuick(&r_glsl, 0);
6114                 r_loadnormalmap = false;
6115                 r_loadgloss = false;
6116                 r_loadfog = true;
6117                 break;
6118         }
6119
6120         R_AnimCache_Free();
6121         R_FrameData_Reset();
6122
6123         r_numqueries = 0;
6124         r_maxqueries = 0;
6125         memset(r_queries, 0, sizeof(r_queries));
6126
6127         r_qwskincache = NULL;
6128         r_qwskincache_size = 0;
6129
6130         // set up r_skinframe loading system for textures
6131         memset(&r_skinframe, 0, sizeof(r_skinframe));
6132         r_skinframe.loadsequence = 1;
6133         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
6134
6135         r_main_texturepool = R_AllocTexturePool();
6136         R_BuildBlankTextures();
6137         R_BuildNoTexture();
6138         if (vid.support.arb_texture_cube_map)
6139         {
6140                 R_BuildWhiteCube();
6141                 R_BuildNormalizationCube();
6142         }
6143         r_texture_fogattenuation = NULL;
6144         r_texture_gammaramps = NULL;
6145         //r_texture_fogintensity = NULL;
6146         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6147         memset(&r_waterstate, 0, sizeof(r_waterstate));
6148         r_glsl_permutation = NULL;
6149         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6150         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
6151         glslshaderstring = NULL;
6152 #ifdef SUPPORTCG
6153         r_cg_permutation = NULL;
6154         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
6155         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
6156         cgshaderstring = NULL;
6157 #endif
6158         memset(&r_svbsp, 0, sizeof (r_svbsp));
6159
6160         r_refdef.fogmasktable_density = 0;
6161 }
6162
6163 void gl_main_shutdown(void)
6164 {
6165         R_AnimCache_Free();
6166         R_FrameData_Reset();
6167
6168         R_Main_FreeViewCache();
6169
6170         if (r_maxqueries)
6171                 qglDeleteQueriesARB(r_maxqueries, r_queries);
6172
6173         r_numqueries = 0;
6174         r_maxqueries = 0;
6175         memset(r_queries, 0, sizeof(r_queries));
6176
6177         r_qwskincache = NULL;
6178         r_qwskincache_size = 0;
6179
6180         // clear out the r_skinframe state
6181         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
6182         memset(&r_skinframe, 0, sizeof(r_skinframe));
6183
6184         if (r_svbsp.nodes)
6185                 Mem_Free(r_svbsp.nodes);
6186         memset(&r_svbsp, 0, sizeof (r_svbsp));
6187         R_FreeTexturePool(&r_main_texturepool);
6188         loadingscreentexture = NULL;
6189         r_texture_blanknormalmap = NULL;
6190         r_texture_white = NULL;
6191         r_texture_grey128 = NULL;
6192         r_texture_black = NULL;
6193         r_texture_whitecube = NULL;
6194         r_texture_normalizationcube = NULL;
6195         r_texture_fogattenuation = NULL;
6196         r_texture_gammaramps = NULL;
6197         r_texture_numcubemaps = 0;
6198         //r_texture_fogintensity = NULL;
6199         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6200         memset(&r_waterstate, 0, sizeof(r_waterstate));
6201         r_glsl_permutation = NULL;
6202         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6203         glslshaderstring = NULL;
6204 #ifdef SUPPORTCG
6205         r_cg_permutation = NULL;
6206         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
6207         cgshaderstring = NULL;
6208 #endif
6209         R_GLSL_Restart_f();
6210 }
6211
6212 extern void CL_ParseEntityLump(char *entitystring);
6213 void gl_main_newmap(void)
6214 {
6215         // FIXME: move this code to client
6216         int l;
6217         char *entities, entname[MAX_QPATH];
6218         if (r_qwskincache)
6219                 Mem_Free(r_qwskincache);
6220         r_qwskincache = NULL;
6221         r_qwskincache_size = 0;
6222         if (cl.worldmodel)
6223         {
6224                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
6225                 l = (int)strlen(entname) - 4;
6226                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
6227                 {
6228                         memcpy(entname + l, ".ent", 5);
6229                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
6230                         {
6231                                 CL_ParseEntityLump(entities);
6232                                 Mem_Free(entities);
6233                                 return;
6234                         }
6235                 }
6236                 if (cl.worldmodel->brush.entities)
6237                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
6238         }
6239         R_Main_FreeViewCache();
6240
6241         R_FrameData_Reset();
6242 }
6243
6244 void GL_Main_Init(void)
6245 {
6246         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
6247
6248         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
6249         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
6250         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
6251         if (gamemode == GAME_NEHAHRA)
6252         {
6253                 Cvar_RegisterVariable (&gl_fogenable);
6254                 Cvar_RegisterVariable (&gl_fogdensity);
6255                 Cvar_RegisterVariable (&gl_fogred);
6256                 Cvar_RegisterVariable (&gl_foggreen);
6257                 Cvar_RegisterVariable (&gl_fogblue);
6258                 Cvar_RegisterVariable (&gl_fogstart);
6259                 Cvar_RegisterVariable (&gl_fogend);
6260                 Cvar_RegisterVariable (&gl_skyclip);
6261         }
6262         Cvar_RegisterVariable(&r_motionblur);
6263         Cvar_RegisterVariable(&r_motionblur_maxblur);
6264         Cvar_RegisterVariable(&r_motionblur_bmin);
6265         Cvar_RegisterVariable(&r_motionblur_vmin);
6266         Cvar_RegisterVariable(&r_motionblur_vmax);
6267         Cvar_RegisterVariable(&r_motionblur_vcoeff);
6268         Cvar_RegisterVariable(&r_motionblur_randomize);
6269         Cvar_RegisterVariable(&r_damageblur);
6270         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
6271         Cvar_RegisterVariable(&r_equalize_entities_minambient);
6272         Cvar_RegisterVariable(&r_equalize_entities_by);
6273         Cvar_RegisterVariable(&r_equalize_entities_to);
6274         Cvar_RegisterVariable(&r_depthfirst);
6275         Cvar_RegisterVariable(&r_useinfinitefarclip);
6276         Cvar_RegisterVariable(&r_farclip_base);
6277         Cvar_RegisterVariable(&r_farclip_world);
6278         Cvar_RegisterVariable(&r_nearclip);
6279         Cvar_RegisterVariable(&r_showbboxes);
6280         Cvar_RegisterVariable(&r_showsurfaces);
6281         Cvar_RegisterVariable(&r_showtris);
6282         Cvar_RegisterVariable(&r_shownormals);
6283         Cvar_RegisterVariable(&r_showlighting);
6284         Cvar_RegisterVariable(&r_showshadowvolumes);
6285         Cvar_RegisterVariable(&r_showcollisionbrushes);
6286         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
6287         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
6288         Cvar_RegisterVariable(&r_showdisabledepthtest);
6289         Cvar_RegisterVariable(&r_drawportals);
6290         Cvar_RegisterVariable(&r_drawentities);
6291         Cvar_RegisterVariable(&r_cullentities_trace);
6292         Cvar_RegisterVariable(&r_cullentities_trace_samples);
6293         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
6294         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
6295         Cvar_RegisterVariable(&r_cullentities_trace_delay);
6296         Cvar_RegisterVariable(&r_drawviewmodel);
6297         Cvar_RegisterVariable(&r_speeds);
6298         Cvar_RegisterVariable(&r_fullbrights);
6299         Cvar_RegisterVariable(&r_wateralpha);
6300         Cvar_RegisterVariable(&r_dynamic);
6301         Cvar_RegisterVariable(&r_fullbright);
6302         Cvar_RegisterVariable(&r_shadows);
6303         Cvar_RegisterVariable(&r_shadows_darken);
6304         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
6305         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
6306         Cvar_RegisterVariable(&r_shadows_throwdistance);
6307         Cvar_RegisterVariable(&r_shadows_throwdirection);
6308         Cvar_RegisterVariable(&r_shadows_focus);
6309         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
6310         Cvar_RegisterVariable(&r_q1bsp_skymasking);
6311         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
6312         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
6313         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
6314         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
6315         Cvar_RegisterVariable(&r_fog_exp2);
6316         Cvar_RegisterVariable(&r_drawfog);
6317         Cvar_RegisterVariable(&r_transparentdepthmasking);
6318         Cvar_RegisterVariable(&r_texture_dds_load);
6319         Cvar_RegisterVariable(&r_texture_dds_save);
6320         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
6321         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
6322         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
6323         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
6324         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
6325         Cvar_RegisterVariable(&r_textureunits);
6326         Cvar_RegisterVariable(&gl_combine);
6327         Cvar_RegisterVariable(&r_glsl);
6328         Cvar_RegisterVariable(&r_glsl_deluxemapping);
6329         Cvar_RegisterVariable(&r_glsl_offsetmapping);
6330         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
6331         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
6332         Cvar_RegisterVariable(&r_glsl_postprocess);
6333         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
6334         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
6335         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
6336         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
6337         Cvar_RegisterVariable(&r_water);
6338         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
6339         Cvar_RegisterVariable(&r_water_clippingplanebias);
6340         Cvar_RegisterVariable(&r_water_refractdistort);
6341         Cvar_RegisterVariable(&r_water_reflectdistort);
6342         Cvar_RegisterVariable(&r_lerpsprites);
6343         Cvar_RegisterVariable(&r_lerpmodels);
6344         Cvar_RegisterVariable(&r_lerplightstyles);
6345         Cvar_RegisterVariable(&r_waterscroll);
6346         Cvar_RegisterVariable(&r_bloom);
6347         Cvar_RegisterVariable(&r_bloom_colorscale);
6348         Cvar_RegisterVariable(&r_bloom_brighten);
6349         Cvar_RegisterVariable(&r_bloom_blur);
6350         Cvar_RegisterVariable(&r_bloom_resolution);
6351         Cvar_RegisterVariable(&r_bloom_colorexponent);
6352         Cvar_RegisterVariable(&r_bloom_colorsubtract);
6353         Cvar_RegisterVariable(&r_hdr);
6354         Cvar_RegisterVariable(&r_hdr_scenebrightness);
6355         Cvar_RegisterVariable(&r_hdr_glowintensity);
6356         Cvar_RegisterVariable(&r_hdr_range);
6357         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
6358         Cvar_RegisterVariable(&developer_texturelogging);
6359         Cvar_RegisterVariable(&gl_lightmaps);
6360         Cvar_RegisterVariable(&r_test);
6361         Cvar_RegisterVariable(&r_batchmode);
6362         Cvar_RegisterVariable(&r_glsl_saturation);
6363         Cvar_RegisterVariable(&r_framedatasize);
6364         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
6365                 Cvar_SetValue("r_fullbrights", 0);
6366         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
6367
6368         Cvar_RegisterVariable(&r_track_sprites);
6369         Cvar_RegisterVariable(&r_track_sprites_flags);
6370         Cvar_RegisterVariable(&r_track_sprites_scalew);
6371         Cvar_RegisterVariable(&r_track_sprites_scaleh);
6372         Cvar_RegisterVariable(&r_overheadsprites_perspective);
6373         Cvar_RegisterVariable(&r_overheadsprites_pushback);
6374 }
6375
6376 extern void R_Textures_Init(void);
6377 extern void GL_Draw_Init(void);
6378 extern void GL_Main_Init(void);
6379 extern void R_Shadow_Init(void);
6380 extern void R_Sky_Init(void);
6381 extern void GL_Surf_Init(void);
6382 extern void R_Particles_Init(void);
6383 extern void R_Explosion_Init(void);
6384 extern void gl_backend_init(void);
6385 extern void Sbar_Init(void);
6386 extern void R_LightningBeams_Init(void);
6387 extern void Mod_RenderInit(void);
6388 extern void Font_Init(void);
6389
6390 void Render_Init(void)
6391 {
6392         gl_backend_init();
6393         R_Textures_Init();
6394         GL_Main_Init();
6395         Font_Init();
6396         GL_Draw_Init();
6397         R_Shadow_Init();
6398         R_Sky_Init();
6399         GL_Surf_Init();
6400         Sbar_Init();
6401         R_Particles_Init();
6402         R_Explosion_Init();
6403         R_LightningBeams_Init();
6404         Mod_RenderInit();
6405 }
6406
6407 /*
6408 ===============
6409 GL_Init
6410 ===============
6411 */
6412 extern char *ENGINE_EXTENSIONS;
6413 void GL_Init (void)
6414 {
6415         gl_renderer = (const char *)qglGetString(GL_RENDERER);
6416         gl_vendor = (const char *)qglGetString(GL_VENDOR);
6417         gl_version = (const char *)qglGetString(GL_VERSION);
6418         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
6419
6420         if (!gl_extensions)
6421                 gl_extensions = "";
6422         if (!gl_platformextensions)
6423                 gl_platformextensions = "";
6424
6425         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
6426         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
6427         Con_Printf("GL_VERSION: %s\n", gl_version);
6428         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
6429         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
6430
6431         VID_CheckExtensions();
6432
6433         // LordHavoc: report supported extensions
6434         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
6435
6436         // clear to black (loading plaque will be seen over this)
6437         CHECKGLERROR
6438         qglClearColor(0,0,0,1);CHECKGLERROR
6439         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
6440 }
6441
6442 int R_CullBox(const vec3_t mins, const vec3_t maxs)
6443 {
6444         int i;
6445         mplane_t *p;
6446         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6447         {
6448                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
6449                 if (i == 4)
6450                         continue;
6451                 p = r_refdef.view.frustum + i;
6452                 switch(p->signbits)
6453                 {
6454                 default:
6455                 case 0:
6456                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6457                                 return true;
6458                         break;
6459                 case 1:
6460                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6461                                 return true;
6462                         break;
6463                 case 2:
6464                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6465                                 return true;
6466                         break;
6467                 case 3:
6468                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6469                                 return true;
6470                         break;
6471                 case 4:
6472                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6473                                 return true;
6474                         break;
6475                 case 5:
6476                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6477                                 return true;
6478                         break;
6479                 case 6:
6480                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6481                                 return true;
6482                         break;
6483                 case 7:
6484                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6485                                 return true;
6486                         break;
6487                 }
6488         }
6489         return false;
6490 }
6491
6492 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
6493 {
6494         int i;
6495         const mplane_t *p;
6496         for (i = 0;i < numplanes;i++)
6497         {
6498                 p = planes + i;
6499                 switch(p->signbits)
6500                 {
6501                 default:
6502                 case 0:
6503                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6504                                 return true;
6505                         break;
6506                 case 1:
6507                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6508                                 return true;
6509                         break;
6510                 case 2:
6511                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6512                                 return true;
6513                         break;
6514                 case 3:
6515                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6516                                 return true;
6517                         break;
6518                 case 4:
6519                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6520                                 return true;
6521                         break;
6522                 case 5:
6523                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6524                                 return true;
6525                         break;
6526                 case 6:
6527                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6528                                 return true;
6529                         break;
6530                 case 7:
6531                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6532                                 return true;
6533                         break;
6534                 }
6535         }
6536         return false;
6537 }
6538
6539 //==================================================================================
6540
6541 // LordHavoc: this stores temporary data used within the same frame
6542
6543 qboolean r_framedata_failed;
6544 static size_t r_framedata_size;
6545 static size_t r_framedata_current;
6546 static void *r_framedata_base;
6547
6548 void R_FrameData_Reset(void)
6549 {
6550         if (r_framedata_base)
6551                 Mem_Free(r_framedata_base);
6552         r_framedata_base = NULL;
6553         r_framedata_size = 0;
6554         r_framedata_current = 0;
6555         r_framedata_failed = false;
6556 }
6557
6558 void R_FrameData_NewFrame(void)
6559 {
6560         size_t wantedsize;
6561         if (r_framedata_failed)
6562                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
6563         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
6564         wantedsize = bound(65536, wantedsize, 128*1024*1024);
6565         if (r_framedata_size != wantedsize)
6566         {
6567                 r_framedata_size = wantedsize;
6568                 if (r_framedata_base)
6569                         Mem_Free(r_framedata_base);
6570                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
6571         }
6572         r_framedata_current = 0;
6573         r_framedata_failed = false;
6574 }
6575
6576 void *R_FrameData_Alloc(size_t size)
6577 {
6578         void *data;
6579
6580         // align to 16 byte boundary
6581         size = (size + 15) & ~15;
6582         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
6583         r_framedata_current += size;
6584
6585         // check overflow
6586         if (r_framedata_current > r_framedata_size)
6587                 r_framedata_failed = true;
6588
6589         // return NULL on everything after a failure
6590         if (r_framedata_failed)
6591                 return NULL;
6592
6593         return data;
6594 }
6595
6596 void *R_FrameData_Store(size_t size, void *data)
6597 {
6598         void *d = R_FrameData_Alloc(size);
6599         if (d)
6600                 memcpy(d, data, size);
6601         return d;
6602 }
6603
6604 //==================================================================================
6605
6606 // LordHavoc: animcache originally written by Echon, rewritten since then
6607
6608 /**
6609  * Animation cache prevents re-generating mesh data for an animated model
6610  * multiple times in one frame for lighting, shadowing, reflections, etc.
6611  */
6612
6613 void R_AnimCache_Free(void)
6614 {
6615 }
6616
6617 void R_AnimCache_ClearCache(void)
6618 {
6619         int i;
6620         entity_render_t *ent;
6621
6622         for (i = 0;i < r_refdef.scene.numentities;i++)
6623         {
6624                 ent = r_refdef.scene.entities[i];
6625                 ent->animcache_vertex3f = NULL;
6626                 ent->animcache_normal3f = NULL;
6627                 ent->animcache_svector3f = NULL;
6628                 ent->animcache_tvector3f = NULL;
6629         }
6630 }
6631
6632 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6633 {
6634         dp_model_t *model = ent->model;
6635         int numvertices;
6636         // see if it's already cached this frame
6637         if (ent->animcache_vertex3f)
6638         {
6639                 // add normals/tangents if needed
6640                 if (wantnormals || wanttangents)
6641                 {
6642                         if (ent->animcache_normal3f)
6643                                 wantnormals = false;
6644                         if (ent->animcache_svector3f)
6645                                 wanttangents = false;
6646                         if (wantnormals || wanttangents)
6647                         {
6648                                 numvertices = model->surfmesh.num_vertices;
6649                                 if (wantnormals)
6650                                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6651                                 if (wanttangents)
6652                                 {
6653                                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6654                                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6655                                 }
6656                                 if (!r_framedata_failed)
6657                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
6658                         }
6659                 }
6660         }
6661         else
6662         {
6663                 // see if this ent is worth caching
6664                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
6665                         return false;
6666                 // get some memory for this entity and generate mesh data
6667                 numvertices = model->surfmesh.num_vertices;
6668                 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6669                 if (wantnormals)
6670                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6671                 if (wanttangents)
6672                 {
6673                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6674                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6675                 }
6676                 if (!r_framedata_failed)
6677                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
6678         }
6679         return !r_framedata_failed;
6680 }
6681
6682 void R_AnimCache_CacheVisibleEntities(void)
6683 {
6684         int i;
6685         qboolean wantnormals = !r_showsurfaces.integer;
6686         qboolean wanttangents = !r_showsurfaces.integer;
6687
6688         switch(vid.renderpath)
6689         {
6690         case RENDERPATH_GL20:
6691         case RENDERPATH_CGGL:
6692                 break;
6693         case RENDERPATH_GL13:
6694         case RENDERPATH_GL11:
6695                 wanttangents = false;
6696                 break;
6697         }
6698
6699         // TODO: thread this
6700         // NOTE: R_PrepareRTLights() also caches entities
6701
6702         for (i = 0;i < r_refdef.scene.numentities;i++)
6703                 if (r_refdef.viewcache.entityvisible[i])
6704                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
6705 }
6706
6707 //==================================================================================
6708
6709 static void R_View_UpdateEntityLighting (void)
6710 {
6711         int i;
6712         entity_render_t *ent;
6713         vec3_t tempdiffusenormal, avg;
6714         vec_t f, fa, fd, fdd;
6715         qboolean skipunseen = r_shadows.integer != 1 || R_Shadow_ShadowMappingEnabled();
6716
6717         for (i = 0;i < r_refdef.scene.numentities;i++)
6718         {
6719                 ent = r_refdef.scene.entities[i];
6720
6721                 // skip unseen models
6722                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
6723                         continue;
6724
6725                 // skip bsp models
6726                 if (ent->model && ent->model->brush.num_leafs)
6727                 {
6728                         // TODO: use modellight for r_ambient settings on world?
6729                         VectorSet(ent->modellight_ambient, 0, 0, 0);
6730                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
6731                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
6732                         continue;
6733                 }
6734
6735                 // fetch the lighting from the worldmodel data
6736                 VectorClear(ent->modellight_ambient);
6737                 VectorClear(ent->modellight_diffuse);
6738                 VectorClear(tempdiffusenormal);
6739                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
6740                 {
6741                         vec3_t org;
6742                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6743                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
6744                         if(ent->flags & RENDER_EQUALIZE)
6745                         {
6746                                 // first fix up ambient lighting...
6747                                 if(r_equalize_entities_minambient.value > 0)
6748                                 {
6749                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
6750                                         if(fd > 0)
6751                                         {
6752                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
6753                                                 if(fa < r_equalize_entities_minambient.value * fd)
6754                                                 {
6755                                                         // solve:
6756                                                         //   fa'/fd' = minambient
6757                                                         //   fa'+0.25*fd' = fa+0.25*fd
6758                                                         //   ...
6759                                                         //   fa' = fd' * minambient
6760                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
6761                                                         //   ...
6762                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
6763                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
6764                                                         //   ...
6765                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
6766                                                         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
6767                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
6768                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6769                                                 }
6770                                         }
6771                                 }
6772
6773                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
6774                                 {
6775                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
6776                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
6777                                         if(f > 0)
6778                                         {
6779                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
6780                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
6781                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6782                                         }
6783                                 }
6784                         }
6785                 }
6786                 else // highly rare
6787                         VectorSet(ent->modellight_ambient, 1, 1, 1);
6788
6789                 // move the light direction into modelspace coordinates for lighting code
6790                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
6791                 if(VectorLength2(ent->modellight_lightdir) == 0)
6792                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
6793                 VectorNormalize(ent->modellight_lightdir);
6794         }
6795 }
6796
6797 #define MAX_LINEOFSIGHTTRACES 64
6798
6799 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
6800 {
6801         int i;
6802         vec3_t boxmins, boxmaxs;
6803         vec3_t start;
6804         vec3_t end;
6805         dp_model_t *model = r_refdef.scene.worldmodel;
6806
6807         if (!model || !model->brush.TraceLineOfSight)
6808                 return true;
6809
6810         // expand the box a little
6811         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
6812         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
6813         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
6814         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
6815         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
6816         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
6817
6818         // return true if eye is inside enlarged box
6819         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
6820                 return true;
6821
6822         // try center
6823         VectorCopy(eye, start);
6824         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
6825         if (model->brush.TraceLineOfSight(model, start, end))
6826                 return true;
6827
6828         // try various random positions
6829         for (i = 0;i < numsamples;i++)
6830         {
6831                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
6832                 if (model->brush.TraceLineOfSight(model, start, end))
6833                         return true;
6834         }
6835
6836         return false;
6837 }
6838
6839
6840 static void R_View_UpdateEntityVisible (void)
6841 {
6842         int i;
6843         int renderimask;
6844         int samples;
6845         entity_render_t *ent;
6846
6847         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
6848                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
6849                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
6850                 :                                                          RENDER_EXTERIORMODEL;
6851         if (!r_drawviewmodel.integer)
6852                 renderimask |= RENDER_VIEWMODEL;
6853         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
6854         {
6855                 // worldmodel can check visibility
6856                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
6857                 for (i = 0;i < r_refdef.scene.numentities;i++)
6858                 {
6859                         ent = r_refdef.scene.entities[i];
6860                         if (!(ent->flags & renderimask))
6861                         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)))
6862                         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))
6863                                 r_refdef.viewcache.entityvisible[i] = true;
6864                 }
6865                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
6866                 {
6867                         for (i = 0;i < r_refdef.scene.numentities;i++)
6868                         {
6869                                 ent = r_refdef.scene.entities[i];
6870                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
6871                                 {
6872                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
6873                                         if (samples < 0)
6874                                                 continue; // temp entities do pvs only
6875                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
6876                                                 ent->last_trace_visibility = realtime;
6877                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
6878                                                 r_refdef.viewcache.entityvisible[i] = 0;
6879                                 }
6880                         }
6881                 }
6882         }
6883         else
6884         {
6885                 // no worldmodel or it can't check visibility
6886                 for (i = 0;i < r_refdef.scene.numentities;i++)
6887                 {
6888                         ent = r_refdef.scene.entities[i];
6889                         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));
6890                 }
6891         }
6892 }
6893
6894 /// only used if skyrendermasked, and normally returns false
6895 int R_DrawBrushModelsSky (void)
6896 {
6897         int i, sky;
6898         entity_render_t *ent;
6899
6900         sky = false;
6901         for (i = 0;i < r_refdef.scene.numentities;i++)
6902         {
6903                 if (!r_refdef.viewcache.entityvisible[i])
6904                         continue;
6905                 ent = r_refdef.scene.entities[i];
6906                 if (!ent->model || !ent->model->DrawSky)
6907                         continue;
6908                 ent->model->DrawSky(ent);
6909                 sky = true;
6910         }
6911         return sky;
6912 }
6913
6914 static void R_DrawNoModel(entity_render_t *ent);
6915 static void R_DrawModels(void)
6916 {
6917         int i;
6918         entity_render_t *ent;
6919
6920         for (i = 0;i < r_refdef.scene.numentities;i++)
6921         {
6922                 if (!r_refdef.viewcache.entityvisible[i])
6923                         continue;
6924                 ent = r_refdef.scene.entities[i];
6925                 r_refdef.stats.entities++;
6926                 if (ent->model && ent->model->Draw != NULL)
6927                         ent->model->Draw(ent);
6928                 else
6929                         R_DrawNoModel(ent);
6930         }
6931 }
6932
6933 static void R_DrawModelsDepth(void)
6934 {
6935         int i;
6936         entity_render_t *ent;
6937
6938         for (i = 0;i < r_refdef.scene.numentities;i++)
6939         {
6940                 if (!r_refdef.viewcache.entityvisible[i])
6941                         continue;
6942                 ent = r_refdef.scene.entities[i];
6943                 if (ent->model && ent->model->DrawDepth != NULL)
6944                         ent->model->DrawDepth(ent);
6945         }
6946 }
6947
6948 static void R_DrawModelsDebug(void)
6949 {
6950         int i;
6951         entity_render_t *ent;
6952
6953         for (i = 0;i < r_refdef.scene.numentities;i++)
6954         {
6955                 if (!r_refdef.viewcache.entityvisible[i])
6956                         continue;
6957                 ent = r_refdef.scene.entities[i];
6958                 if (ent->model && ent->model->DrawDebug != NULL)
6959                         ent->model->DrawDebug(ent);
6960         }
6961 }
6962
6963 static void R_DrawModelsAddWaterPlanes(void)
6964 {
6965         int i;
6966         entity_render_t *ent;
6967
6968         for (i = 0;i < r_refdef.scene.numentities;i++)
6969         {
6970                 if (!r_refdef.viewcache.entityvisible[i])
6971                         continue;
6972                 ent = r_refdef.scene.entities[i];
6973                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
6974                         ent->model->DrawAddWaterPlanes(ent);
6975         }
6976 }
6977
6978 static void R_View_SetFrustum(void)
6979 {
6980         int i;
6981         double slopex, slopey;
6982         vec3_t forward, left, up, origin;
6983
6984         // we can't trust r_refdef.view.forward and friends in reflected scenes
6985         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
6986
6987 #if 0
6988         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
6989         r_refdef.view.frustum[0].normal[1] = 0 - 0;
6990         r_refdef.view.frustum[0].normal[2] = -1 - 0;
6991         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
6992         r_refdef.view.frustum[1].normal[1] = 0 + 0;
6993         r_refdef.view.frustum[1].normal[2] = -1 + 0;
6994         r_refdef.view.frustum[2].normal[0] = 0 - 0;
6995         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
6996         r_refdef.view.frustum[2].normal[2] = -1 - 0;
6997         r_refdef.view.frustum[3].normal[0] = 0 + 0;
6998         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
6999         r_refdef.view.frustum[3].normal[2] = -1 + 0;
7000 #endif
7001
7002 #if 0
7003         zNear = r_refdef.nearclip;
7004         nudge = 1.0 - 1.0 / (1<<23);
7005         r_refdef.view.frustum[4].normal[0] = 0 - 0;
7006         r_refdef.view.frustum[4].normal[1] = 0 - 0;
7007         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
7008         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
7009         r_refdef.view.frustum[5].normal[0] = 0 + 0;
7010         r_refdef.view.frustum[5].normal[1] = 0 + 0;
7011         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
7012         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
7013 #endif
7014
7015
7016
7017 #if 0
7018         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
7019         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
7020         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
7021         r_refdef.view.frustum[0].dist = m[15] - m[12];
7022
7023         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
7024         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
7025         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
7026         r_refdef.view.frustum[1].dist = m[15] + m[12];
7027
7028         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
7029         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
7030         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
7031         r_refdef.view.frustum[2].dist = m[15] - m[13];
7032
7033         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
7034         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
7035         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
7036         r_refdef.view.frustum[3].dist = m[15] + m[13];
7037
7038         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
7039         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
7040         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
7041         r_refdef.view.frustum[4].dist = m[15] - m[14];
7042
7043         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
7044         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
7045         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
7046         r_refdef.view.frustum[5].dist = m[15] + m[14];
7047 #endif
7048
7049         if (r_refdef.view.useperspective)
7050         {
7051                 slopex = 1.0 / r_refdef.view.frustum_x;
7052                 slopey = 1.0 / r_refdef.view.frustum_y;
7053                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
7054                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
7055                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
7056                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
7057                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7058
7059                 // Leaving those out was a mistake, those were in the old code, and they
7060                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
7061                 // I couldn't reproduce it after adding those normalizations. --blub
7062                 VectorNormalize(r_refdef.view.frustum[0].normal);
7063                 VectorNormalize(r_refdef.view.frustum[1].normal);
7064                 VectorNormalize(r_refdef.view.frustum[2].normal);
7065                 VectorNormalize(r_refdef.view.frustum[3].normal);
7066
7067                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
7068                 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]);
7069                 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]);
7070                 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]);
7071                 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]);
7072
7073                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
7074                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
7075                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
7076                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
7077                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7078         }
7079         else
7080         {
7081                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
7082                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
7083                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
7084                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
7085                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7086                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
7087                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
7088                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
7089                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
7090                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7091         }
7092         r_refdef.view.numfrustumplanes = 5;
7093
7094         if (r_refdef.view.useclipplane)
7095         {
7096                 r_refdef.view.numfrustumplanes = 6;
7097                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
7098         }
7099
7100         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7101                 PlaneClassify(r_refdef.view.frustum + i);
7102
7103         // LordHavoc: note to all quake engine coders, Quake had a special case
7104         // for 90 degrees which assumed a square view (wrong), so I removed it,
7105         // Quake2 has it disabled as well.
7106
7107         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
7108         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
7109         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
7110         //PlaneClassify(&frustum[0]);
7111
7112         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
7113         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
7114         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
7115         //PlaneClassify(&frustum[1]);
7116
7117         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
7118         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
7119         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
7120         //PlaneClassify(&frustum[2]);
7121
7122         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
7123         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
7124         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
7125         //PlaneClassify(&frustum[3]);
7126
7127         // nearclip plane
7128         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
7129         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
7130         //PlaneClassify(&frustum[4]);
7131 }
7132
7133 void R_View_Update(void)
7134 {
7135         R_Main_ResizeViewCache();
7136         R_View_SetFrustum();
7137         R_View_WorldVisibility(r_refdef.view.useclipplane);
7138         R_View_UpdateEntityVisible();
7139         R_View_UpdateEntityLighting();
7140 }
7141
7142 void R_SetupView(qboolean allowwaterclippingplane)
7143 {
7144         const float *customclipplane = NULL;
7145         float plane[4];
7146         if (r_refdef.view.useclipplane && allowwaterclippingplane)
7147         {
7148                 // LordHavoc: couldn't figure out how to make this approach the
7149                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
7150                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
7151                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
7152                         dist = r_refdef.view.clipplane.dist;
7153                 plane[0] = r_refdef.view.clipplane.normal[0];
7154                 plane[1] = r_refdef.view.clipplane.normal[1];
7155                 plane[2] = r_refdef.view.clipplane.normal[2];
7156                 plane[3] = dist;
7157                 customclipplane = plane;
7158         }
7159
7160         if (!r_refdef.view.useperspective)
7161                 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);
7162         else if (vid.stencil && r_useinfinitefarclip.integer)
7163                 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);
7164         else
7165                 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);
7166         R_SetViewport(&r_refdef.view.viewport);
7167 }
7168
7169 void R_EntityMatrix(const matrix4x4_t *matrix)
7170 {
7171         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
7172         {
7173                 gl_modelmatrixchanged = false;
7174                 gl_modelmatrix = *matrix;
7175                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
7176                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
7177                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
7178                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
7179                 CHECKGLERROR
7180                 switch(vid.renderpath)
7181                 {
7182                 case RENDERPATH_GL20:
7183                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
7184                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
7185                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7186                         break;
7187                 case RENDERPATH_CGGL:
7188 #ifdef SUPPORTCG
7189                         CHECKCGERROR
7190                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
7191                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
7192                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7193 #endif
7194                         break;
7195                 case RENDERPATH_GL13:
7196                 case RENDERPATH_GL11:
7197                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7198                         break;
7199                 }
7200         }
7201 }
7202
7203 void R_ResetViewRendering2D(void)
7204 {
7205         r_viewport_t viewport;
7206         DrawQ_Finish();
7207
7208         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
7209         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);
7210         R_SetViewport(&viewport);
7211         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
7212         GL_Color(1, 1, 1, 1);
7213         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7214         GL_BlendFunc(GL_ONE, GL_ZERO);
7215         GL_AlphaTest(false);
7216         GL_ScissorTest(false);
7217         GL_DepthMask(false);
7218         GL_DepthRange(0, 1);
7219         GL_DepthTest(false);
7220         R_EntityMatrix(&identitymatrix);
7221         R_Mesh_ResetTextureState();
7222         GL_PolygonOffset(0, 0);
7223         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7224         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7225         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7226         qglStencilMask(~0);CHECKGLERROR
7227         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7228         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7229         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
7230 }
7231
7232 void R_ResetViewRendering3D(void)
7233 {
7234         DrawQ_Finish();
7235
7236         R_SetupView(true);
7237         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7238         GL_Color(1, 1, 1, 1);
7239         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7240         GL_BlendFunc(GL_ONE, GL_ZERO);
7241         GL_AlphaTest(false);
7242         GL_ScissorTest(true);
7243         GL_DepthMask(true);
7244         GL_DepthRange(0, 1);
7245         GL_DepthTest(true);
7246         R_EntityMatrix(&identitymatrix);
7247         R_Mesh_ResetTextureState();
7248         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7249         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7250         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7251         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7252         qglStencilMask(~0);CHECKGLERROR
7253         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7254         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7255         GL_CullFace(r_refdef.view.cullface_back);
7256 }
7257
7258 void R_RenderScene(void);
7259 void R_RenderWaterPlanes(void);
7260
7261 static void R_Water_StartFrame(void)
7262 {
7263         int i;
7264         int waterwidth, waterheight, texturewidth, textureheight;
7265         r_waterstate_waterplane_t *p;
7266
7267         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
7268                 return;
7269
7270         switch(vid.renderpath)
7271         {
7272         case RENDERPATH_GL20:
7273         case RENDERPATH_CGGL:
7274                 break;
7275         case RENDERPATH_GL13:
7276         case RENDERPATH_GL11:
7277                 return;
7278         }
7279
7280         // set waterwidth and waterheight to the water resolution that will be
7281         // used (often less than the screen resolution for faster rendering)
7282         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
7283         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
7284
7285         // calculate desired texture sizes
7286         // can't use water if the card does not support the texture size
7287         if (!r_water.integer || r_showsurfaces.integer)
7288                 texturewidth = textureheight = waterwidth = waterheight = 0;
7289         else if (vid.support.arb_texture_non_power_of_two)
7290         {
7291                 texturewidth = waterwidth;
7292                 textureheight = waterheight;
7293         }
7294         else
7295         {
7296                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
7297                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
7298         }
7299
7300         // allocate textures as needed
7301         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
7302         {
7303                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7304                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
7305                 {
7306                         if (p->texture_refraction)
7307                                 R_FreeTexture(p->texture_refraction);
7308                         p->texture_refraction = NULL;
7309                         if (p->texture_reflection)
7310                                 R_FreeTexture(p->texture_reflection);
7311                         p->texture_reflection = NULL;
7312                 }
7313                 memset(&r_waterstate, 0, sizeof(r_waterstate));
7314                 r_waterstate.texturewidth = texturewidth;
7315                 r_waterstate.textureheight = textureheight;
7316         }
7317
7318         if (r_waterstate.texturewidth)
7319         {
7320                 r_waterstate.enabled = true;
7321
7322                 // when doing a reduced render (HDR) we want to use a smaller area
7323                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
7324                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
7325
7326                 // set up variables that will be used in shader setup
7327                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7328                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7329                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7330                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7331         }
7332
7333         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7334         r_waterstate.numwaterplanes = 0;
7335 }
7336
7337 void R_Water_AddWaterPlane(msurface_t *surface)
7338 {
7339         int triangleindex, planeindex;
7340         const int *e;
7341         vec3_t vert[3];
7342         vec3_t normal;
7343         vec3_t center;
7344         mplane_t plane;
7345         r_waterstate_waterplane_t *p;
7346         texture_t *t = R_GetCurrentTexture(surface->texture);
7347         // just use the first triangle with a valid normal for any decisions
7348         VectorClear(normal);
7349         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
7350         {
7351                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
7352                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
7353                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
7354                 TriangleNormal(vert[0], vert[1], vert[2], normal);
7355                 if (VectorLength2(normal) >= 0.001)
7356                         break;
7357         }
7358
7359         VectorCopy(normal, plane.normal);
7360         VectorNormalize(plane.normal);
7361         plane.dist = DotProduct(vert[0], plane.normal);
7362         PlaneClassify(&plane);
7363         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
7364         {
7365                 // skip backfaces (except if nocullface is set)
7366                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
7367                         return;
7368                 VectorNegate(plane.normal, plane.normal);
7369                 plane.dist *= -1;
7370                 PlaneClassify(&plane);
7371         }
7372
7373
7374         // find a matching plane if there is one
7375         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7376                 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
7377                         break;
7378         if (planeindex >= r_waterstate.maxwaterplanes)
7379                 return; // nothing we can do, out of planes
7380
7381         // if this triangle does not fit any known plane rendered this frame, add one
7382         if (planeindex >= r_waterstate.numwaterplanes)
7383         {
7384                 // store the new plane
7385                 r_waterstate.numwaterplanes++;
7386                 p->plane = plane;
7387                 // clear materialflags and pvs
7388                 p->materialflags = 0;
7389                 p->pvsvalid = false;
7390         }
7391         // merge this surface's materialflags into the waterplane
7392         p->materialflags |= t->currentmaterialflags;
7393         // merge this surface's PVS into the waterplane
7394         VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
7395         if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
7396          && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
7397         {
7398                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
7399                 p->pvsvalid = true;
7400         }
7401 }
7402
7403 static void R_Water_ProcessPlanes(void)
7404 {
7405         r_refdef_view_t originalview;
7406         r_refdef_view_t myview;
7407         int planeindex;
7408         r_waterstate_waterplane_t *p;
7409
7410         originalview = r_refdef.view;
7411
7412         // make sure enough textures are allocated
7413         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7414         {
7415                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7416                 {
7417                         if (!p->texture_refraction)
7418                                 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);
7419                         if (!p->texture_refraction)
7420                                 goto error;
7421                 }
7422
7423                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7424                 {
7425                         if (!p->texture_reflection)
7426                                 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);
7427                         if (!p->texture_reflection)
7428                                 goto error;
7429                 }
7430         }
7431
7432         // render views
7433         r_refdef.view = originalview;
7434         r_refdef.view.showdebug = false;
7435         r_refdef.view.width = r_waterstate.waterwidth;
7436         r_refdef.view.height = r_waterstate.waterheight;
7437         r_refdef.view.useclipplane = true;
7438         myview = r_refdef.view;
7439         r_waterstate.renderingscene = true;
7440         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7441         {
7442                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7443                 {
7444                         r_refdef.view = myview;
7445                         // render reflected scene and copy into texture
7446                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
7447                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
7448                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
7449                         r_refdef.view.clipplane = p->plane;
7450                         // reverse the cullface settings for this render
7451                         r_refdef.view.cullface_front = GL_FRONT;
7452                         r_refdef.view.cullface_back = GL_BACK;
7453                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
7454                         {
7455                                 r_refdef.view.usecustompvs = true;
7456                                 if (p->pvsvalid)
7457                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7458                                 else
7459                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7460                         }
7461
7462                         R_ResetViewRendering3D();
7463                         R_ClearScreen(r_refdef.fogenabled);
7464                         R_View_Update();
7465                         R_RenderScene();
7466
7467                         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);
7468                 }
7469
7470                 // render the normal view scene and copy into texture
7471                 // (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)
7472                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7473                 {
7474                         r_waterstate.renderingrefraction = true;
7475                         r_refdef.view = myview;
7476                         r_refdef.view.clipplane = p->plane;
7477                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
7478                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
7479                         PlaneClassify(&r_refdef.view.clipplane);
7480
7481                         R_ResetViewRendering3D();
7482                         R_ClearScreen(r_refdef.fogenabled);
7483                         R_View_Update();
7484                         R_RenderScene();
7485
7486                         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);
7487                         r_waterstate.renderingrefraction = false;
7488                 }
7489
7490         }
7491         r_waterstate.renderingscene = false;
7492         r_refdef.view = originalview;
7493         R_ResetViewRendering3D();
7494         R_ClearScreen(r_refdef.fogenabled);
7495         R_View_Update();
7496         return;
7497 error:
7498         r_refdef.view = originalview;
7499         r_waterstate.renderingscene = false;
7500         Cvar_SetValueQuick(&r_water, 0);
7501         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
7502         return;
7503 }
7504
7505 void R_Bloom_StartFrame(void)
7506 {
7507         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
7508
7509         switch(vid.renderpath)
7510         {
7511         case RENDERPATH_GL20:
7512         case RENDERPATH_CGGL:
7513                 break;
7514         case RENDERPATH_GL13:
7515         case RENDERPATH_GL11:
7516                 return;
7517         }
7518
7519         // set bloomwidth and bloomheight to the bloom resolution that will be
7520         // used (often less than the screen resolution for faster rendering)
7521         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
7522         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
7523         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
7524         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
7525         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
7526
7527         // calculate desired texture sizes
7528         if (vid.support.arb_texture_non_power_of_two)
7529         {
7530                 screentexturewidth = r_refdef.view.width;
7531                 screentextureheight = r_refdef.view.height;
7532                 bloomtexturewidth = r_bloomstate.bloomwidth;
7533                 bloomtextureheight = r_bloomstate.bloomheight;
7534         }
7535         else
7536         {
7537                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
7538                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
7539                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
7540                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
7541         }
7542
7543         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))
7544         {
7545                 Cvar_SetValueQuick(&r_hdr, 0);
7546                 Cvar_SetValueQuick(&r_bloom, 0);
7547                 Cvar_SetValueQuick(&r_motionblur, 0);
7548                 Cvar_SetValueQuick(&r_damageblur, 0);
7549         }
7550
7551         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)))
7552                 screentexturewidth = screentextureheight = 0;
7553         if (!r_hdr.integer && !r_bloom.integer)
7554                 bloomtexturewidth = bloomtextureheight = 0;
7555
7556         // allocate textures as needed
7557         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
7558         {
7559                 if (r_bloomstate.texture_screen)
7560                         R_FreeTexture(r_bloomstate.texture_screen);
7561                 r_bloomstate.texture_screen = NULL;
7562                 r_bloomstate.screentexturewidth = screentexturewidth;
7563                 r_bloomstate.screentextureheight = screentextureheight;
7564                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
7565                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
7566         }
7567         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
7568         {
7569                 if (r_bloomstate.texture_bloom)
7570                         R_FreeTexture(r_bloomstate.texture_bloom);
7571                 r_bloomstate.texture_bloom = NULL;
7572                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
7573                 r_bloomstate.bloomtextureheight = bloomtextureheight;
7574                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
7575                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7576         }
7577
7578         // when doing a reduced render (HDR) we want to use a smaller area
7579         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
7580         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
7581         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
7582         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
7583         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
7584
7585         // set up a texcoord array for the full resolution screen image
7586         // (we have to keep this around to copy back during final render)
7587         r_bloomstate.screentexcoord2f[0] = 0;
7588         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7589         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7590         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7591         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7592         r_bloomstate.screentexcoord2f[5] = 0;
7593         r_bloomstate.screentexcoord2f[6] = 0;
7594         r_bloomstate.screentexcoord2f[7] = 0;
7595
7596         // set up a texcoord array for the reduced resolution bloom image
7597         // (which will be additive blended over the screen image)
7598         r_bloomstate.bloomtexcoord2f[0] = 0;
7599         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7600         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7601         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7602         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7603         r_bloomstate.bloomtexcoord2f[5] = 0;
7604         r_bloomstate.bloomtexcoord2f[6] = 0;
7605         r_bloomstate.bloomtexcoord2f[7] = 0;
7606
7607         if (r_hdr.integer || r_bloom.integer)
7608         {
7609                 r_bloomstate.enabled = true;
7610                 r_bloomstate.hdr = r_hdr.integer != 0;
7611         }
7612
7613         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);
7614 }
7615
7616 void R_Bloom_CopyBloomTexture(float colorscale)
7617 {
7618         r_refdef.stats.bloom++;
7619
7620         // scale down screen texture to the bloom texture size
7621         CHECKGLERROR
7622         R_SetViewport(&r_bloomstate.viewport);
7623         GL_BlendFunc(GL_ONE, GL_ZERO);
7624         GL_Color(colorscale, colorscale, colorscale, 1);
7625         // TODO: optimize with multitexture or GLSL
7626         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7627         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7628         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7629         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7630
7631         // we now have a bloom image in the framebuffer
7632         // copy it into the bloom image texture for later processing
7633         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);
7634         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7635 }
7636
7637 void R_Bloom_CopyHDRTexture(void)
7638 {
7639         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);
7640         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7641 }
7642
7643 void R_Bloom_MakeTexture(void)
7644 {
7645         int x, range, dir;
7646         float xoffset, yoffset, r, brighten;
7647
7648         r_refdef.stats.bloom++;
7649
7650         R_ResetViewRendering2D();
7651         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7652         R_Mesh_ColorPointer(NULL, 0, 0);
7653
7654         // we have a bloom image in the framebuffer
7655         CHECKGLERROR
7656         R_SetViewport(&r_bloomstate.viewport);
7657
7658         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
7659         {
7660                 x *= 2;
7661                 r = bound(0, r_bloom_colorexponent.value / x, 1);
7662                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7663                 GL_Color(r, r, r, 1);
7664                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7665                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7666                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7667                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7668
7669                 // copy the vertically blurred bloom view to a texture
7670                 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);
7671                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7672         }
7673
7674         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
7675         brighten = r_bloom_brighten.value;
7676         if (r_hdr.integer)
7677                 brighten *= r_hdr_range.value;
7678         brighten = sqrt(brighten);
7679         if(range >= 1)
7680                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
7681         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7682         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
7683
7684         for (dir = 0;dir < 2;dir++)
7685         {
7686                 // blend on at multiple vertical offsets to achieve a vertical blur
7687                 // TODO: do offset blends using GLSL
7688                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
7689                 GL_BlendFunc(GL_ONE, GL_ZERO);
7690                 for (x = -range;x <= range;x++)
7691                 {
7692                         if (!dir){xoffset = 0;yoffset = x;}
7693                         else {xoffset = x;yoffset = 0;}
7694                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
7695                         yoffset /= (float)r_bloomstate.bloomtextureheight;
7696                         // compute a texcoord array with the specified x and y offset
7697                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
7698                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7699                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7700                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7701                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7702                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
7703                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
7704                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
7705                         // this r value looks like a 'dot' particle, fading sharply to
7706                         // black at the edges
7707                         // (probably not realistic but looks good enough)
7708                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
7709                         //r = brighten/(range*2+1);
7710                         r = brighten / (range * 2 + 1);
7711                         if(range >= 1)
7712                                 r *= (1 - x*x/(float)(range*range));
7713                         GL_Color(r, r, r, 1);
7714                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7715                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7716                         GL_BlendFunc(GL_ONE, GL_ONE);
7717                 }
7718
7719                 // copy the vertically blurred bloom view to a texture
7720                 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);
7721                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7722         }
7723
7724         // apply subtract last
7725         // (just like it would be in a GLSL shader)
7726         if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
7727         {
7728                 GL_BlendFunc(GL_ONE, GL_ZERO);
7729                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7730                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7731                 GL_Color(1, 1, 1, 1);
7732                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7733                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7734
7735                 GL_BlendFunc(GL_ONE, GL_ONE);
7736                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
7737                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7738                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7739                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
7740                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7741                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7742                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
7743
7744                 // copy the darkened bloom view to a texture
7745                 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);
7746                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7747         }
7748 }
7749
7750 void R_HDR_RenderBloomTexture(void)
7751 {
7752         int oldwidth, oldheight;
7753         float oldcolorscale;
7754
7755         oldcolorscale = r_refdef.view.colorscale;
7756         oldwidth = r_refdef.view.width;
7757         oldheight = r_refdef.view.height;
7758         r_refdef.view.width = r_bloomstate.bloomwidth;
7759         r_refdef.view.height = r_bloomstate.bloomheight;
7760
7761         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
7762         // TODO: add exposure compensation features
7763         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
7764
7765         r_refdef.view.showdebug = false;
7766         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
7767
7768         R_ResetViewRendering3D();
7769
7770         R_ClearScreen(r_refdef.fogenabled);
7771         if (r_timereport_active)
7772                 R_TimeReport("HDRclear");
7773
7774         R_View_Update();
7775         if (r_timereport_active)
7776                 R_TimeReport("visibility");
7777
7778         // only do secondary renders with HDR if r_hdr is 2 or higher
7779         r_waterstate.numwaterplanes = 0;
7780         if (r_waterstate.enabled && r_hdr.integer >= 2)
7781                 R_RenderWaterPlanes();
7782
7783         r_refdef.view.showdebug = true;
7784         R_RenderScene();
7785         r_waterstate.numwaterplanes = 0;
7786
7787         R_ResetViewRendering2D();
7788
7789         R_Bloom_CopyHDRTexture();
7790         R_Bloom_MakeTexture();
7791
7792         // restore the view settings
7793         r_refdef.view.width = oldwidth;
7794         r_refdef.view.height = oldheight;
7795         r_refdef.view.colorscale = oldcolorscale;
7796
7797         R_ResetViewRendering3D();
7798
7799         R_ClearScreen(r_refdef.fogenabled);
7800         if (r_timereport_active)
7801                 R_TimeReport("viewclear");
7802 }
7803
7804 static void R_BlendView(void)
7805 {
7806         unsigned int permutation;
7807         float uservecs[4][4];
7808
7809         switch (vid.renderpath)
7810         {
7811         case RENDERPATH_GL20:
7812         case RENDERPATH_CGGL:
7813                 permutation =
7814                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
7815                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
7816                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
7817                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
7818                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
7819
7820                 if (r_bloomstate.texture_screen)
7821                 {
7822                         // make sure the buffer is available
7823                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
7824
7825                         R_ResetViewRendering2D();
7826                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7827                         R_Mesh_ColorPointer(NULL, 0, 0);
7828
7829                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
7830                         {
7831                                 // declare variables
7832                                 float speed;
7833                                 static float avgspeed;
7834
7835                                 speed = VectorLength(cl.movement_velocity);
7836
7837                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
7838                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
7839
7840                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
7841                                 speed = bound(0, speed, 1);
7842                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
7843
7844                                 // calculate values into a standard alpha
7845                                 cl.motionbluralpha = 1 - exp(-
7846                                                 (
7847                                                  (r_motionblur.value * speed / 80)
7848                                                  +
7849                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
7850                                                 )
7851                                                 /
7852                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
7853                                            );
7854
7855                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
7856                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
7857                                 // apply the blur
7858                                 if (cl.motionbluralpha > 0)
7859                                 {
7860                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7861                                         GL_Color(1, 1, 1, cl.motionbluralpha);
7862                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7863                                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7864                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7865                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7866                                 }
7867                         }
7868
7869                         // copy view into the screen texture
7870                         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);
7871                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7872                 }
7873                 else if (!r_bloomstate.texture_bloom)
7874                 {
7875                         // we may still have to do view tint...
7876                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7877                         {
7878                                 // apply a color tint to the whole view
7879                                 R_ResetViewRendering2D();
7880                                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7881                                 R_Mesh_ColorPointer(NULL, 0, 0);
7882                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7883                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7884                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7885                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7886                         }
7887                         break; // no screen processing, no bloom, skip it
7888                 }
7889
7890                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
7891                 {
7892                         // render simple bloom effect
7893                         // copy the screen and shrink it and darken it for the bloom process
7894                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
7895                         // make the bloom texture
7896                         R_Bloom_MakeTexture();
7897                 }
7898
7899 #if _MSC_VER >= 1400
7900 #define sscanf sscanf_s
7901 #endif
7902                 memset(uservecs, 0, sizeof(uservecs));
7903                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
7904                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
7905                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
7906                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
7907
7908                 R_ResetViewRendering2D();
7909                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7910                 R_Mesh_ColorPointer(NULL, 0, 0);
7911                 GL_Color(1, 1, 1, 1);
7912                 GL_BlendFunc(GL_ONE, GL_ZERO);
7913                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7914                 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7915
7916                 switch(vid.renderpath)
7917                 {
7918                 case RENDERPATH_GL20:
7919                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
7920                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
7921                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
7922                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
7923                         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]);
7924                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
7925                         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]);
7926                         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]);
7927                         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]);
7928                         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]);
7929                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
7930                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
7931                         break;
7932                 case RENDERPATH_CGGL:
7933 #ifdef SUPPORTCG
7934                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
7935                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
7936                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
7937                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
7938                         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
7939                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
7940                         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
7941                         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
7942                         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
7943                         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
7944                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
7945                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
7946 #endif
7947                         break;
7948                 default:
7949                         break;
7950                 }
7951                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7952                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7953                 break;
7954         case RENDERPATH_GL13:
7955         case RENDERPATH_GL11:
7956                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7957                 {
7958                         // apply a color tint to the whole view
7959                         R_ResetViewRendering2D();
7960                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7961                         R_Mesh_ColorPointer(NULL, 0, 0);
7962                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7963                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7964                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7965                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7966                 }
7967                 break;
7968         }
7969 }
7970
7971 matrix4x4_t r_waterscrollmatrix;
7972
7973 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
7974 {
7975         if (r_refdef.fog_density)
7976         {
7977                 r_refdef.fogcolor[0] = r_refdef.fog_red;
7978                 r_refdef.fogcolor[1] = r_refdef.fog_green;
7979                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7980
7981                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7982                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7983                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7984                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7985
7986                 {
7987                         vec3_t fogvec;
7988                         VectorCopy(r_refdef.fogcolor, fogvec);
7989                         //   color.rgb *= ContrastBoost * SceneBrightness;
7990                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7991                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7992                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7993                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7994                 }
7995         }
7996 }
7997
7998 void R_UpdateVariables(void)
7999 {
8000         R_Textures_Frame();
8001
8002         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
8003
8004         r_refdef.farclip = r_farclip_base.value;
8005         if (r_refdef.scene.worldmodel)
8006                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
8007         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
8008
8009         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
8010                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
8011         r_refdef.polygonfactor = 0;
8012         r_refdef.polygonoffset = 0;
8013         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8014         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8015
8016         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
8017         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
8018         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
8019         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
8020         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
8021         if (r_showsurfaces.integer)
8022         {
8023                 r_refdef.scene.rtworld = false;
8024                 r_refdef.scene.rtworldshadows = false;
8025                 r_refdef.scene.rtdlight = false;
8026                 r_refdef.scene.rtdlightshadows = false;
8027                 r_refdef.lightmapintensity = 0;
8028         }
8029
8030         if (gamemode == GAME_NEHAHRA)
8031         {
8032                 if (gl_fogenable.integer)
8033                 {
8034                         r_refdef.oldgl_fogenable = true;
8035                         r_refdef.fog_density = gl_fogdensity.value;
8036                         r_refdef.fog_red = gl_fogred.value;
8037                         r_refdef.fog_green = gl_foggreen.value;
8038                         r_refdef.fog_blue = gl_fogblue.value;
8039                         r_refdef.fog_alpha = 1;
8040                         r_refdef.fog_start = 0;
8041                         r_refdef.fog_end = gl_skyclip.value;
8042                         r_refdef.fog_height = 1<<30;
8043                         r_refdef.fog_fadedepth = 128;
8044                 }
8045                 else if (r_refdef.oldgl_fogenable)
8046                 {
8047                         r_refdef.oldgl_fogenable = false;
8048                         r_refdef.fog_density = 0;
8049                         r_refdef.fog_red = 0;
8050                         r_refdef.fog_green = 0;
8051                         r_refdef.fog_blue = 0;
8052                         r_refdef.fog_alpha = 0;
8053                         r_refdef.fog_start = 0;
8054                         r_refdef.fog_end = 0;
8055                         r_refdef.fog_height = 1<<30;
8056                         r_refdef.fog_fadedepth = 128;
8057                 }
8058         }
8059
8060         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
8061         r_refdef.fog_start = max(0, r_refdef.fog_start);
8062         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
8063
8064         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
8065
8066         if (r_refdef.fog_density && r_drawfog.integer)
8067         {
8068                 r_refdef.fogenabled = true;
8069                 // this is the point where the fog reaches 0.9986 alpha, which we
8070                 // consider a good enough cutoff point for the texture
8071                 // (0.9986 * 256 == 255.6)
8072                 if (r_fog_exp2.integer)
8073                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
8074                 else
8075                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
8076                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
8077                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
8078                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
8079                 // fog color was already set
8080                 // update the fog texture
8081                 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)
8082                         R_BuildFogTexture();
8083         }
8084         else
8085                 r_refdef.fogenabled = false;
8086
8087         switch(vid.renderpath)
8088         {
8089         case RENDERPATH_GL20:
8090         case RENDERPATH_CGGL:
8091                 if(v_glslgamma.integer && !vid_gammatables_trivial)
8092                 {
8093                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
8094                         {
8095                                 // build GLSL gamma texture
8096 #define RAMPWIDTH 256
8097                                 unsigned short ramp[RAMPWIDTH * 3];
8098                                 unsigned char rampbgr[RAMPWIDTH][4];
8099                                 int i;
8100
8101                                 r_texture_gammaramps_serial = vid_gammatables_serial;
8102
8103                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
8104                                 for(i = 0; i < RAMPWIDTH; ++i)
8105                                 {
8106                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8107                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8108                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
8109                                         rampbgr[i][3] = 0;
8110                                 }
8111                                 if (r_texture_gammaramps)
8112                                 {
8113                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
8114                                 }
8115                                 else
8116                                 {
8117                                         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);
8118                                 }
8119                         }
8120                 }
8121                 else
8122                 {
8123                         // remove GLSL gamma texture
8124                 }
8125                 break;
8126         case RENDERPATH_GL13:
8127         case RENDERPATH_GL11:
8128                 break;
8129         }
8130 }
8131
8132 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
8133 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
8134 /*
8135 ================
8136 R_SelectScene
8137 ================
8138 */
8139 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
8140         if( scenetype != r_currentscenetype ) {
8141                 // store the old scenetype
8142                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
8143                 r_currentscenetype = scenetype;
8144                 // move in the new scene
8145                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
8146         }
8147 }
8148
8149 /*
8150 ================
8151 R_GetScenePointer
8152 ================
8153 */
8154 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
8155 {
8156         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
8157         if( scenetype == r_currentscenetype ) {
8158                 return &r_refdef.scene;
8159         } else {
8160                 return &r_scenes_store[ scenetype ];
8161         }
8162 }
8163
8164 /*
8165 ================
8166 R_RenderView
8167 ================
8168 */
8169 void R_RenderView(void)
8170 {
8171         if (r_timereport_active)
8172                 R_TimeReport("start");
8173         r_textureframe++; // used only by R_GetCurrentTexture
8174         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8175
8176         if (!r_drawentities.integer)
8177                 r_refdef.scene.numentities = 0;
8178
8179         R_AnimCache_ClearCache();
8180         R_FrameData_NewFrame();
8181
8182         if (r_refdef.view.isoverlay)
8183         {
8184                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
8185                 GL_Clear( GL_DEPTH_BUFFER_BIT );
8186                 R_TimeReport("depthclear");
8187
8188                 r_refdef.view.showdebug = false;
8189
8190                 r_waterstate.enabled = false;
8191                 r_waterstate.numwaterplanes = 0;
8192
8193                 R_RenderScene();
8194
8195                 CHECKGLERROR
8196                 return;
8197         }
8198
8199         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
8200                 return; //Host_Error ("R_RenderView: NULL worldmodel");
8201
8202         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
8203
8204         // break apart the view matrix into vectors for various purposes
8205         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8206         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8207         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8208         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8209         // make an inverted copy of the view matrix for tracking sprites
8210         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8211
8212         R_Shadow_UpdateWorldLightSelection();
8213
8214         R_Bloom_StartFrame();
8215         R_Water_StartFrame();
8216
8217         CHECKGLERROR
8218         if (r_timereport_active)
8219                 R_TimeReport("viewsetup");
8220
8221         R_ResetViewRendering3D();
8222
8223         if (r_refdef.view.clear || r_refdef.fogenabled)
8224         {
8225                 R_ClearScreen(r_refdef.fogenabled);
8226                 if (r_timereport_active)
8227                         R_TimeReport("viewclear");
8228         }
8229         r_refdef.view.clear = true;
8230
8231         // this produces a bloom texture to be used in R_BlendView() later
8232         if (r_hdr.integer && r_bloomstate.bloomwidth)
8233         {
8234                 R_HDR_RenderBloomTexture();
8235                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
8236                 r_textureframe++; // used only by R_GetCurrentTexture
8237         }
8238
8239         r_refdef.view.showdebug = true;
8240
8241         R_View_Update();
8242         if (r_timereport_active)
8243                 R_TimeReport("visibility");
8244
8245         r_waterstate.numwaterplanes = 0;
8246         if (r_waterstate.enabled)
8247                 R_RenderWaterPlanes();
8248
8249         R_RenderScene();
8250         r_waterstate.numwaterplanes = 0;
8251
8252         R_BlendView();
8253         if (r_timereport_active)
8254                 R_TimeReport("blendview");
8255
8256         GL_Scissor(0, 0, vid.width, vid.height);
8257         GL_ScissorTest(false);
8258         CHECKGLERROR
8259 }
8260
8261 void R_RenderWaterPlanes(void)
8262 {
8263         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
8264         {
8265                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
8266                 if (r_timereport_active)
8267                         R_TimeReport("waterworld");
8268         }
8269
8270         // don't let sound skip if going slow
8271         if (r_refdef.scene.extraupdate)
8272                 S_ExtraUpdate ();
8273
8274         R_DrawModelsAddWaterPlanes();
8275         if (r_timereport_active)
8276                 R_TimeReport("watermodels");
8277
8278         if (r_waterstate.numwaterplanes)
8279         {
8280                 R_Water_ProcessPlanes();
8281                 if (r_timereport_active)
8282                         R_TimeReport("waterscenes");
8283         }
8284 }
8285
8286 extern void R_DrawLightningBeams (void);
8287 extern void VM_CL_AddPolygonsToMeshQueue (void);
8288 extern void R_DrawPortals (void);
8289 extern cvar_t cl_locs_show;
8290 static void R_DrawLocs(void);
8291 static void R_DrawEntityBBoxes(void);
8292 static void R_DrawModelDecals(void);
8293 extern void R_DrawModelShadows(void);
8294 extern void R_DrawModelShadowMaps(void);
8295 extern cvar_t cl_decals_newsystem;
8296 extern qboolean r_shadow_usingdeferredprepass;
8297 void R_RenderScene(void)
8298 {
8299         qboolean shadowmapping = false;
8300
8301         r_refdef.stats.renders++;
8302
8303         R_UpdateFogColor();
8304
8305         // don't let sound skip if going slow
8306         if (r_refdef.scene.extraupdate)
8307                 S_ExtraUpdate ();
8308
8309         R_MeshQueue_BeginScene();
8310
8311         R_SkyStartFrame();
8312
8313         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);
8314
8315         if (cl.csqc_vidvars.drawworld)
8316         {
8317                 // don't let sound skip if going slow
8318                 if (r_refdef.scene.extraupdate)
8319                         S_ExtraUpdate ();
8320
8321                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
8322                 {
8323                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
8324                         if (r_timereport_active)
8325                                 R_TimeReport("worldsky");
8326                 }
8327
8328                 if (R_DrawBrushModelsSky() && r_timereport_active)
8329                         R_TimeReport("bmodelsky");
8330
8331                 if (skyrendermasked && skyrenderlater)
8332                 {
8333                         // we have to force off the water clipping plane while rendering sky
8334                         R_SetupView(false);
8335                         R_Sky();
8336                         R_SetupView(true);
8337                         if (r_timereport_active)
8338                                 R_TimeReport("sky");
8339                 }
8340         }
8341
8342         R_AnimCache_CacheVisibleEntities();
8343         if (r_timereport_active)
8344                 R_TimeReport("animation");
8345
8346         R_Shadow_PrepareLights();
8347         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
8348                 R_Shadow_PrepareModelShadows();
8349         if (r_timereport_active)
8350                 R_TimeReport("preparelights");
8351
8352         if (R_Shadow_ShadowMappingEnabled())
8353                 shadowmapping = true;
8354
8355         if (r_shadow_usingdeferredprepass)
8356                 R_Shadow_DrawPrepass();
8357
8358         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
8359         {
8360                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
8361                 if (r_timereport_active)
8362                         R_TimeReport("worlddepth");
8363         }
8364         if (r_depthfirst.integer >= 2)
8365         {
8366                 R_DrawModelsDepth();
8367                 if (r_timereport_active)
8368                         R_TimeReport("modeldepth");
8369         }
8370
8371         if (r_shadows.integer > 0 && shadowmapping && r_refdef.lightmapintensity > 0)
8372         {
8373                 R_DrawModelShadowMaps();
8374                 R_ResetViewRendering3D();
8375                 // don't let sound skip if going slow
8376                 if (r_refdef.scene.extraupdate)
8377                         S_ExtraUpdate ();
8378         }
8379
8380         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
8381         {
8382                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
8383                 if (r_timereport_active)
8384                         R_TimeReport("world");
8385         }
8386
8387         // don't let sound skip if going slow
8388         if (r_refdef.scene.extraupdate)
8389                 S_ExtraUpdate ();
8390
8391         R_DrawModels();
8392         if (r_timereport_active)
8393                 R_TimeReport("models");
8394
8395         // don't let sound skip if going slow
8396         if (r_refdef.scene.extraupdate)
8397                 S_ExtraUpdate ();
8398
8399         if (r_shadows.integer > 0 && !shadowmapping && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8400         {
8401                 R_DrawModelShadows();
8402                 R_ResetViewRendering3D();
8403                 // don't let sound skip if going slow
8404                 if (r_refdef.scene.extraupdate)
8405                         S_ExtraUpdate ();
8406         }
8407
8408         if (!r_shadow_usingdeferredprepass)
8409         {
8410                 R_Shadow_DrawLights();
8411                 if (r_timereport_active)
8412                         R_TimeReport("rtlights");
8413         }
8414
8415         // don't let sound skip if going slow
8416         if (r_refdef.scene.extraupdate)
8417                 S_ExtraUpdate ();
8418
8419         if (r_shadows.integer > 0 && !shadowmapping && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8420         {
8421                 R_DrawModelShadows();
8422                 R_ResetViewRendering3D();
8423                 // don't let sound skip if going slow
8424                 if (r_refdef.scene.extraupdate)
8425                         S_ExtraUpdate ();
8426         }
8427
8428         if (cl.csqc_vidvars.drawworld)
8429         {
8430                 if (cl_decals_newsystem.integer)
8431                 {
8432                         R_DrawModelDecals();
8433                         if (r_timereport_active)
8434                                 R_TimeReport("modeldecals");
8435                 }
8436                 else
8437                 {
8438                         R_DrawDecals();
8439                         if (r_timereport_active)
8440                                 R_TimeReport("decals");
8441                 }
8442
8443                 R_DrawParticles();
8444                 if (r_timereport_active)
8445                         R_TimeReport("particles");
8446
8447                 R_DrawExplosions();
8448                 if (r_timereport_active)
8449                         R_TimeReport("explosions");
8450
8451                 R_DrawLightningBeams();
8452                 if (r_timereport_active)
8453                         R_TimeReport("lightning");
8454         }
8455
8456         VM_CL_AddPolygonsToMeshQueue();
8457
8458         if (r_refdef.view.showdebug)
8459         {
8460                 if (cl_locs_show.integer)
8461                 {
8462                         R_DrawLocs();
8463                         if (r_timereport_active)
8464                                 R_TimeReport("showlocs");
8465                 }
8466
8467                 if (r_drawportals.integer)
8468                 {
8469                         R_DrawPortals();
8470                         if (r_timereport_active)
8471                                 R_TimeReport("portals");
8472                 }
8473
8474                 if (r_showbboxes.value > 0)
8475                 {
8476                         R_DrawEntityBBoxes();
8477                         if (r_timereport_active)
8478                                 R_TimeReport("bboxes");
8479                 }
8480         }
8481
8482         R_MeshQueue_RenderTransparent();
8483         if (r_timereport_active)
8484                 R_TimeReport("drawtrans");
8485
8486         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))
8487         {
8488                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
8489                 if (r_timereport_active)
8490                         R_TimeReport("worlddebug");
8491                 R_DrawModelsDebug();
8492                 if (r_timereport_active)
8493                         R_TimeReport("modeldebug");
8494         }
8495
8496         if (cl.csqc_vidvars.drawworld)
8497         {
8498                 R_Shadow_DrawCoronas();
8499                 if (r_timereport_active)
8500                         R_TimeReport("coronas");
8501         }
8502
8503         // don't let sound skip if going slow
8504         if (r_refdef.scene.extraupdate)
8505                 S_ExtraUpdate ();
8506
8507         R_ResetViewRendering2D();
8508 }
8509
8510 static const unsigned short bboxelements[36] =
8511 {
8512         5, 1, 3, 5, 3, 7,
8513         6, 2, 0, 6, 0, 4,
8514         7, 3, 2, 7, 2, 6,
8515         4, 0, 1, 4, 1, 5,
8516         4, 5, 7, 4, 7, 6,
8517         1, 0, 2, 1, 2, 3,
8518 };
8519
8520 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
8521 {
8522         int i;
8523         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
8524
8525         RSurf_ActiveWorldEntity();
8526
8527         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8528         GL_DepthMask(false);
8529         GL_DepthRange(0, 1);
8530         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8531         R_Mesh_ResetTextureState();
8532
8533         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
8534         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
8535         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
8536         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
8537         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
8538         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
8539         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
8540         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
8541         R_FillColors(color4f, 8, cr, cg, cb, ca);
8542         if (r_refdef.fogenabled)
8543         {
8544                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
8545                 {
8546                         f1 = RSurf_FogVertex(v);
8547                         f2 = 1 - f1;
8548                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
8549                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
8550                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
8551                 }
8552         }
8553         R_Mesh_VertexPointer(vertex3f, 0, 0);
8554         R_Mesh_ColorPointer(color4f, 0, 0);
8555         R_Mesh_ResetTextureState();
8556         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8557         R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
8558 }
8559
8560 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8561 {
8562         int i;
8563         float color[4];
8564         prvm_edict_t *edict;
8565         prvm_prog_t *prog_save = prog;
8566
8567         // this function draws bounding boxes of server entities
8568         if (!sv.active)
8569                 return;
8570
8571         GL_CullFace(GL_NONE);
8572         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8573
8574         prog = 0;
8575         SV_VM_Begin();
8576         for (i = 0;i < numsurfaces;i++)
8577         {
8578                 edict = PRVM_EDICT_NUM(surfacelist[i]);
8579                 switch ((int)edict->fields.server->solid)
8580                 {
8581                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
8582                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
8583                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
8584                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
8585                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
8586                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
8587                 }
8588                 color[3] *= r_showbboxes.value;
8589                 color[3] = bound(0, color[3], 1);
8590                 GL_DepthTest(!r_showdisabledepthtest.integer);
8591                 GL_CullFace(r_refdef.view.cullface_front);
8592                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
8593         }
8594         SV_VM_End();
8595         prog = prog_save;
8596 }
8597
8598 static void R_DrawEntityBBoxes(void)
8599 {
8600         int i;
8601         prvm_edict_t *edict;
8602         vec3_t center;
8603         prvm_prog_t *prog_save = prog;
8604
8605         // this function draws bounding boxes of server entities
8606         if (!sv.active)
8607                 return;
8608
8609         prog = 0;
8610         SV_VM_Begin();
8611         for (i = 0;i < prog->num_edicts;i++)
8612         {
8613                 edict = PRVM_EDICT_NUM(i);
8614                 if (edict->priv.server->free)
8615                         continue;
8616                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
8617                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
8618                         continue;
8619                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
8620                         continue;
8621                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
8622                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
8623         }
8624         SV_VM_End();
8625         prog = prog_save;
8626 }
8627
8628 static const int nomodelelement3i[24] =
8629 {
8630         5, 2, 0,
8631         5, 1, 2,
8632         5, 0, 3,
8633         5, 3, 1,
8634         0, 2, 4,
8635         2, 1, 4,
8636         3, 0, 4,
8637         1, 3, 4
8638 };
8639
8640 static const unsigned short nomodelelement3s[24] =
8641 {
8642         5, 2, 0,
8643         5, 1, 2,
8644         5, 0, 3,
8645         5, 3, 1,
8646         0, 2, 4,
8647         2, 1, 4,
8648         3, 0, 4,
8649         1, 3, 4
8650 };
8651
8652 static const float nomodelvertex3f[6*3] =
8653 {
8654         -16,   0,   0,
8655          16,   0,   0,
8656           0, -16,   0,
8657           0,  16,   0,
8658           0,   0, -16,
8659           0,   0,  16
8660 };
8661
8662 static const float nomodelcolor4f[6*4] =
8663 {
8664         0.0f, 0.0f, 0.5f, 1.0f,
8665         0.0f, 0.0f, 0.5f, 1.0f,
8666         0.0f, 0.5f, 0.0f, 1.0f,
8667         0.0f, 0.5f, 0.0f, 1.0f,
8668         0.5f, 0.0f, 0.0f, 1.0f,
8669         0.5f, 0.0f, 0.0f, 1.0f
8670 };
8671
8672 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8673 {
8674         int i;
8675         float f1, f2, *c;
8676         float color4f[6*4];
8677
8678         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);
8679
8680         // this is only called once per entity so numsurfaces is always 1, and
8681         // surfacelist is always {0}, so this code does not handle batches
8682
8683         if (rsurface.ent_flags & RENDER_ADDITIVE)
8684         {
8685                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
8686                 GL_DepthMask(false);
8687         }
8688         else if (rsurface.colormod[3] < 1)
8689         {
8690                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8691                 GL_DepthMask(false);
8692         }
8693         else
8694         {
8695                 GL_BlendFunc(GL_ONE, GL_ZERO);
8696                 GL_DepthMask(true);
8697         }
8698         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8699         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8700         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8701         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8702         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8703         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
8704         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8705         R_Mesh_ColorPointer(color4f, 0, 0);
8706         for (i = 0, c = color4f;i < 6;i++, c += 4)
8707         {
8708                 c[0] *= rsurface.colormod[0];
8709                 c[1] *= rsurface.colormod[1];
8710                 c[2] *= rsurface.colormod[2];
8711                 c[3] *= rsurface.colormod[3];
8712         }
8713         if (r_refdef.fogenabled)
8714         {
8715                 for (i = 0, c = color4f;i < 6;i++, c += 4)
8716                 {
8717                         f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
8718                         f2 = 1 - f1;
8719                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8720                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8721                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8722                 }
8723         }
8724         R_Mesh_ResetTextureState();
8725         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
8726 }
8727
8728 void R_DrawNoModel(entity_render_t *ent)
8729 {
8730         vec3_t org;
8731         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8732         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8733                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8734         else
8735                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8736 }
8737
8738 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8739 {
8740         vec3_t right1, right2, diff, normal;
8741
8742         VectorSubtract (org2, org1, normal);
8743
8744         // calculate 'right' vector for start
8745         VectorSubtract (r_refdef.view.origin, org1, diff);
8746         CrossProduct (normal, diff, right1);
8747         VectorNormalize (right1);
8748
8749         // calculate 'right' vector for end
8750         VectorSubtract (r_refdef.view.origin, org2, diff);
8751         CrossProduct (normal, diff, right2);
8752         VectorNormalize (right2);
8753
8754         vert[ 0] = org1[0] + width * right1[0];
8755         vert[ 1] = org1[1] + width * right1[1];
8756         vert[ 2] = org1[2] + width * right1[2];
8757         vert[ 3] = org1[0] - width * right1[0];
8758         vert[ 4] = org1[1] - width * right1[1];
8759         vert[ 5] = org1[2] - width * right1[2];
8760         vert[ 6] = org2[0] - width * right2[0];
8761         vert[ 7] = org2[1] - width * right2[1];
8762         vert[ 8] = org2[2] - width * right2[2];
8763         vert[ 9] = org2[0] + width * right2[0];
8764         vert[10] = org2[1] + width * right2[1];
8765         vert[11] = org2[2] + width * right2[2];
8766 }
8767
8768 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)
8769 {
8770         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8771         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8772         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8773         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8774         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8775         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8776         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8777         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8778         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8779         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8780         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8781         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8782 }
8783
8784 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8785 {
8786         int i;
8787         float *vertex3f;
8788         float v[3];
8789         VectorSet(v, x, y, z);
8790         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8791                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8792                         break;
8793         if (i == mesh->numvertices)
8794         {
8795                 if (mesh->numvertices < mesh->maxvertices)
8796                 {
8797                         VectorCopy(v, vertex3f);
8798                         mesh->numvertices++;
8799                 }
8800                 return mesh->numvertices;
8801         }
8802         else
8803                 return i;
8804 }
8805
8806 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8807 {
8808         int i;
8809         int *e, element[3];
8810         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8811         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8812         e = mesh->element3i + mesh->numtriangles * 3;
8813         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8814         {
8815                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8816                 if (mesh->numtriangles < mesh->maxtriangles)
8817                 {
8818                         *e++ = element[0];
8819                         *e++ = element[1];
8820                         *e++ = element[2];
8821                         mesh->numtriangles++;
8822                 }
8823                 element[1] = element[2];
8824         }
8825 }
8826
8827 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8828 {
8829         int i;
8830         int *e, element[3];
8831         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8832         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8833         e = mesh->element3i + mesh->numtriangles * 3;
8834         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8835         {
8836                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8837                 if (mesh->numtriangles < mesh->maxtriangles)
8838                 {
8839                         *e++ = element[0];
8840                         *e++ = element[1];
8841                         *e++ = element[2];
8842                         mesh->numtriangles++;
8843                 }
8844                 element[1] = element[2];
8845         }
8846 }
8847
8848 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8849 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8850 {
8851         int planenum, planenum2;
8852         int w;
8853         int tempnumpoints;
8854         mplane_t *plane, *plane2;
8855         double maxdist;
8856         double temppoints[2][256*3];
8857         // figure out how large a bounding box we need to properly compute this brush
8858         maxdist = 0;
8859         for (w = 0;w < numplanes;w++)
8860                 maxdist = max(maxdist, fabs(planes[w].dist));
8861         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8862         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8863         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8864         {
8865                 w = 0;
8866                 tempnumpoints = 4;
8867                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8868                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8869                 {
8870                         if (planenum2 == planenum)
8871                                 continue;
8872                         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);
8873                         w = !w;
8874                 }
8875                 if (tempnumpoints < 3)
8876                         continue;
8877                 // generate elements forming a triangle fan for this polygon
8878                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8879         }
8880 }
8881
8882 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)
8883 {
8884         texturelayer_t *layer;
8885         layer = t->currentlayers + t->currentnumlayers++;
8886         layer->type = type;
8887         layer->depthmask = depthmask;
8888         layer->blendfunc1 = blendfunc1;
8889         layer->blendfunc2 = blendfunc2;
8890         layer->texture = texture;
8891         layer->texmatrix = *matrix;
8892         layer->color[0] = r;
8893         layer->color[1] = g;
8894         layer->color[2] = b;
8895         layer->color[3] = a;
8896 }
8897
8898 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8899 {
8900         double index, f;
8901         index = parms[2] + r_refdef.scene.time * parms[3];
8902         index -= floor(index);
8903         switch (func)
8904         {
8905         default:
8906         case Q3WAVEFUNC_NONE:
8907         case Q3WAVEFUNC_NOISE:
8908         case Q3WAVEFUNC_COUNT:
8909                 f = 0;
8910                 break;
8911         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8912         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8913         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8914         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8915         case Q3WAVEFUNC_TRIANGLE:
8916                 index *= 4;
8917                 f = index - floor(index);
8918                 if (index < 1)
8919                         f = f;
8920                 else if (index < 2)
8921                         f = 1 - f;
8922                 else if (index < 3)
8923                         f = -f;
8924                 else
8925                         f = -(1 - f);
8926                 break;
8927         }
8928         return (float)(parms[0] + parms[1] * f);
8929 }
8930
8931 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8932 {
8933         int w, h, idx;
8934         float f;
8935         float tcmat[12];
8936         matrix4x4_t matrix, temp;
8937         switch(tcmod->tcmod)
8938         {
8939                 case Q3TCMOD_COUNT:
8940                 case Q3TCMOD_NONE:
8941                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8942                                 matrix = r_waterscrollmatrix;
8943                         else
8944                                 matrix = identitymatrix;
8945                         break;
8946                 case Q3TCMOD_ENTITYTRANSLATE:
8947                         // this is used in Q3 to allow the gamecode to control texcoord
8948                         // scrolling on the entity, which is not supported in darkplaces yet.
8949                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8950                         break;
8951                 case Q3TCMOD_ROTATE:
8952                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8953                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
8954                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8955                         break;
8956                 case Q3TCMOD_SCALE:
8957                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8958                         break;
8959                 case Q3TCMOD_SCROLL:
8960                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
8961                         break;
8962                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8963                         w = (int) tcmod->parms[0];
8964                         h = (int) tcmod->parms[1];
8965                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
8966                         f = f - floor(f);
8967                         idx = (int) floor(f * w * h);
8968                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8969                         break;
8970                 case Q3TCMOD_STRETCH:
8971                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8972                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8973                         break;
8974                 case Q3TCMOD_TRANSFORM:
8975                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8976                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8977                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8978                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8979                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8980                         break;
8981                 case Q3TCMOD_TURBULENT:
8982                         // this is handled in the RSurf_PrepareVertices function
8983                         matrix = identitymatrix;
8984                         break;
8985         }
8986         temp = *texmatrix;
8987         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8988 }
8989
8990 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8991 {
8992         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
8993         char name[MAX_QPATH];
8994         skinframe_t *skinframe;
8995         unsigned char pixels[296*194];
8996         strlcpy(cache->name, skinname, sizeof(cache->name));
8997         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8998         if (developer_loading.integer)
8999                 Con_Printf("loading %s\n", name);
9000         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
9001         if (!skinframe || !skinframe->base)
9002         {
9003                 unsigned char *f;
9004                 fs_offset_t filesize;
9005                 skinframe = NULL;
9006                 f = FS_LoadFile(name, tempmempool, true, &filesize);
9007                 if (f)
9008                 {
9009                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
9010                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
9011                         Mem_Free(f);
9012                 }
9013         }
9014         cache->skinframe = skinframe;
9015 }
9016
9017 texture_t *R_GetCurrentTexture(texture_t *t)
9018 {
9019         int i;
9020         const entity_render_t *ent = rsurface.entity;
9021         dp_model_t *model = ent->model;
9022         q3shaderinfo_layer_tcmod_t *tcmod;
9023
9024         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
9025                 return t->currentframe;
9026         t->update_lastrenderframe = r_textureframe;
9027         t->update_lastrenderentity = (void *)ent;
9028
9029         // switch to an alternate material if this is a q1bsp animated material
9030         {
9031                 texture_t *texture = t;
9032                 int s = rsurface.ent_skinnum;
9033                 if ((unsigned int)s >= (unsigned int)model->numskins)
9034                         s = 0;
9035                 if (model->skinscenes)
9036                 {
9037                         if (model->skinscenes[s].framecount > 1)
9038                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
9039                         else
9040                                 s = model->skinscenes[s].firstframe;
9041                 }
9042                 if (s > 0)
9043                         t = t + s * model->num_surfaces;
9044                 if (t->animated)
9045                 {
9046                         // use an alternate animation if the entity's frame is not 0,
9047                         // and only if the texture has an alternate animation
9048                         if (rsurface.ent_alttextures && t->anim_total[1])
9049                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
9050                         else
9051                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
9052                 }
9053                 texture->currentframe = t;
9054         }
9055
9056         // update currentskinframe to be a qw skin or animation frame
9057         if (rsurface.ent_qwskin >= 0)
9058         {
9059                 i = rsurface.ent_qwskin;
9060                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
9061                 {
9062                         r_qwskincache_size = cl.maxclients;
9063                         if (r_qwskincache)
9064                                 Mem_Free(r_qwskincache);
9065                         r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
9066                 }
9067                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
9068                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
9069                 t->currentskinframe = r_qwskincache[i].skinframe;
9070                 if (t->currentskinframe == NULL)
9071                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9072         }
9073         else if (t->numskinframes >= 2)
9074                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9075         if (t->backgroundnumskinframes >= 2)
9076                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
9077
9078         t->currentmaterialflags = t->basematerialflags;
9079         t->currentalpha = rsurface.colormod[3];
9080         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
9081                 t->currentalpha *= r_wateralpha.value;
9082         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
9083                 t->currentalpha *= t->r_water_wateralpha;
9084         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
9085                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
9086         if (!(rsurface.ent_flags & RENDER_LIGHT))
9087                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
9088         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
9089         {
9090                 // pick a model lighting mode
9091                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
9092                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
9093                 else
9094                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
9095         }
9096         if (rsurface.ent_flags & RENDER_ADDITIVE)
9097                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9098         else if (t->currentalpha < 1)
9099                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9100         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
9101                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
9102         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
9103                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
9104         if (t->backgroundnumskinframes)
9105                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
9106         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
9107         {
9108                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
9109                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
9110         }
9111         else
9112                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
9113         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
9114                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
9115
9116         // there is no tcmod
9117         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9118         {
9119                 t->currenttexmatrix = r_waterscrollmatrix;
9120                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
9121         }
9122         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
9123         {
9124                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
9125                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
9126         }
9127
9128         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9129                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
9130         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9131                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
9132
9133         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
9134         if (t->currentskinframe->qpixels)
9135                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
9136         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
9137         if (!t->basetexture)
9138                 t->basetexture = r_texture_notexture;
9139         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
9140         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
9141         t->nmaptexture = t->currentskinframe->nmap;
9142         if (!t->nmaptexture)
9143                 t->nmaptexture = r_texture_blanknormalmap;
9144         t->glosstexture = r_texture_black;
9145         t->glowtexture = t->currentskinframe->glow;
9146         t->fogtexture = t->currentskinframe->fog;
9147         t->reflectmasktexture = t->currentskinframe->reflect;
9148         if (t->backgroundnumskinframes)
9149         {
9150                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
9151                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
9152                 t->backgroundglosstexture = r_texture_black;
9153                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
9154                 if (!t->backgroundnmaptexture)
9155                         t->backgroundnmaptexture = r_texture_blanknormalmap;
9156         }
9157         else
9158         {
9159                 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
9160                 t->backgroundnmaptexture = r_texture_blanknormalmap;
9161                 t->backgroundglosstexture = r_texture_black;
9162                 t->backgroundglowtexture = NULL;
9163         }
9164         t->specularpower = r_shadow_glossexponent.value;
9165         // TODO: store reference values for these in the texture?
9166         t->specularscale = 0;
9167         if (r_shadow_gloss.integer > 0)
9168         {
9169                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
9170                 {
9171                         if (r_shadow_glossintensity.value > 0)
9172                         {
9173                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
9174                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
9175                                 t->specularscale = r_shadow_glossintensity.value;
9176                         }
9177                 }
9178                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
9179                 {
9180                         t->glosstexture = r_texture_white;
9181                         t->backgroundglosstexture = r_texture_white;
9182                         t->specularscale = r_shadow_gloss2intensity.value;
9183                         t->specularpower = r_shadow_gloss2exponent.value;
9184                 }
9185         }
9186         t->specularscale *= t->specularscalemod;
9187         t->specularpower *= t->specularpowermod;
9188
9189         // lightmaps mode looks bad with dlights using actual texturing, so turn
9190         // off the colormap and glossmap, but leave the normalmap on as it still
9191         // accurately represents the shading involved
9192         if (gl_lightmaps.integer)
9193         {
9194                 t->basetexture = r_texture_grey128;
9195                 t->pantstexture = r_texture_black;
9196                 t->shirttexture = r_texture_black;
9197                 t->nmaptexture = r_texture_blanknormalmap;
9198                 t->glosstexture = r_texture_black;
9199                 t->glowtexture = NULL;
9200                 t->fogtexture = NULL;
9201                 t->reflectmasktexture = NULL;
9202                 t->backgroundbasetexture = NULL;
9203                 t->backgroundnmaptexture = r_texture_blanknormalmap;
9204                 t->backgroundglosstexture = r_texture_black;
9205                 t->backgroundglowtexture = NULL;
9206                 t->specularscale = 0;
9207                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
9208         }
9209
9210         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
9211         VectorClear(t->dlightcolor);
9212         t->currentnumlayers = 0;
9213         if (t->currentmaterialflags & MATERIALFLAG_WALL)
9214         {
9215                 int blendfunc1, blendfunc2;
9216                 qboolean depthmask;
9217                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
9218                 {
9219                         blendfunc1 = GL_SRC_ALPHA;
9220                         blendfunc2 = GL_ONE;
9221                 }
9222                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
9223                 {
9224                         blendfunc1 = GL_SRC_ALPHA;
9225                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
9226                 }
9227                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9228                 {
9229                         blendfunc1 = t->customblendfunc[0];
9230                         blendfunc2 = t->customblendfunc[1];
9231                 }
9232                 else
9233                 {
9234                         blendfunc1 = GL_ONE;
9235                         blendfunc2 = GL_ZERO;
9236                 }
9237                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
9238                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9239                 {
9240                         // fullbright is not affected by r_refdef.lightmapintensity
9241                         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]);
9242                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9243                                 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]);
9244                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9245                                 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]);
9246                 }
9247                 else
9248                 {
9249                         vec3_t ambientcolor;
9250                         float colorscale;
9251                         // set the color tint used for lights affecting this surface
9252                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
9253                         colorscale = 2;
9254                         // q3bsp has no lightmap updates, so the lightstylevalue that
9255                         // would normally be baked into the lightmap must be
9256                         // applied to the color
9257                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
9258                         if (model->type == mod_brushq3)
9259                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
9260                         colorscale *= r_refdef.lightmapintensity;
9261                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
9262                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
9263                         // basic lit geometry
9264                         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]);
9265                         // add pants/shirt if needed
9266                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9267                                 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]);
9268                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9269                                 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]);
9270                         // now add ambient passes if needed
9271                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
9272                         {
9273                                 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]);
9274                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9275                                         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]);
9276                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9277                                         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]);
9278                         }
9279                 }
9280                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
9281                         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]);
9282                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
9283                 {
9284                         // if this is opaque use alpha blend which will darken the earlier
9285                         // passes cheaply.
9286                         //
9287                         // if this is an alpha blended material, all the earlier passes
9288                         // were darkened by fog already, so we only need to add the fog
9289                         // color ontop through the fog mask texture
9290                         //
9291                         // if this is an additive blended material, all the earlier passes
9292                         // were darkened by fog already, and we should not add fog color
9293                         // (because the background was not darkened, there is no fog color
9294                         // that was lost behind it).
9295                         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]);
9296                 }
9297         }
9298
9299         return t->currentframe;
9300 }
9301
9302 rsurfacestate_t rsurface;
9303
9304 void R_Mesh_ResizeArrays(int newvertices)
9305 {
9306         float *base;
9307         if (rsurface.array_size >= newvertices)
9308                 return;
9309         if (rsurface.array_modelvertex3f)
9310                 Mem_Free(rsurface.array_modelvertex3f);
9311         rsurface.array_size = (newvertices + 1023) & ~1023;
9312         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
9313         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
9314         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
9315         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
9316         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
9317         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
9318         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
9319         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
9320         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
9321         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
9322         rsurface.array_color4f           = base + rsurface.array_size * 27;
9323         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
9324 }
9325
9326 void RSurf_ActiveWorldEntity(void)
9327 {
9328         dp_model_t *model = r_refdef.scene.worldmodel;
9329         //if (rsurface.entity == r_refdef.scene.worldentity)
9330         //      return;
9331         rsurface.entity = r_refdef.scene.worldentity;
9332         rsurface.skeleton = NULL;
9333         rsurface.ent_skinnum = 0;
9334         rsurface.ent_qwskin = -1;
9335         rsurface.ent_shadertime = 0;
9336         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
9337         if (rsurface.array_size < model->surfmesh.num_vertices)
9338                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9339         rsurface.matrix = identitymatrix;
9340         rsurface.inversematrix = identitymatrix;
9341         rsurface.matrixscale = 1;
9342         rsurface.inversematrixscale = 1;
9343         R_EntityMatrix(&identitymatrix);
9344         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
9345         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
9346         rsurface.fograngerecip = r_refdef.fograngerecip;
9347         rsurface.fogheightfade = r_refdef.fogheightfade;
9348         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
9349         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9350         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9351         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9352         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9353         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9354         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9355         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
9356         rsurface.colormod[3] = 1;
9357         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);
9358         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9359         rsurface.frameblend[0].lerp = 1;
9360         rsurface.ent_alttextures = false;
9361         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9362         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9363         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
9364         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9365         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9366         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9367         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9368         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9369         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9370         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9371         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9372         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
9373         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9374         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9375         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
9376         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9377         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9378         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
9379         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9380         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9381         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
9382         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9383         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9384         rsurface.modelelement3i = model->surfmesh.data_element3i;
9385         rsurface.modelelement3s = model->surfmesh.data_element3s;
9386         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9387         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9388         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9389         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9390         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9391         rsurface.modelsurfaces = model->data_surfaces;
9392         rsurface.generatedvertex = false;
9393         rsurface.vertex3f  = rsurface.modelvertex3f;
9394         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9395         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9396         rsurface.svector3f = rsurface.modelsvector3f;
9397         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9398         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9399         rsurface.tvector3f = rsurface.modeltvector3f;
9400         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9401         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9402         rsurface.normal3f  = rsurface.modelnormal3f;
9403         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9404         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9405         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9406 }
9407
9408 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
9409 {
9410         dp_model_t *model = ent->model;
9411         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
9412         //      return;
9413         rsurface.entity = (entity_render_t *)ent;
9414         rsurface.skeleton = ent->skeleton;
9415         rsurface.ent_skinnum = ent->skinnum;
9416         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;
9417         rsurface.ent_shadertime = ent->shadertime;
9418         rsurface.ent_flags = ent->flags;
9419         if (rsurface.array_size < model->surfmesh.num_vertices)
9420                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9421         rsurface.matrix = ent->matrix;
9422         rsurface.inversematrix = ent->inversematrix;
9423         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9424         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9425         R_EntityMatrix(&rsurface.matrix);
9426         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9427         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9428         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9429         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9430         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9431         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9432         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
9433         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
9434         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
9435         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
9436         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
9437         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
9438         rsurface.colormod[3] = ent->alpha;
9439         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
9440         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
9441         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
9442         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9443         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9444         if (ent->model->brush.submodel && !prepass)
9445         {
9446                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
9447                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
9448         }
9449         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
9450         {
9451                 if (ent->animcache_vertex3f && !r_framedata_failed)
9452                 {
9453                         rsurface.modelvertex3f = ent->animcache_vertex3f;
9454                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
9455                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
9456                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
9457                 }
9458                 else if (wanttangents)
9459                 {
9460                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9461                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9462                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9463                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9464                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
9465                 }
9466                 else if (wantnormals)
9467                 {
9468                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9469                         rsurface.modelsvector3f = NULL;
9470                         rsurface.modeltvector3f = NULL;
9471                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9472                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
9473                 }
9474                 else
9475                 {
9476                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9477                         rsurface.modelsvector3f = NULL;
9478                         rsurface.modeltvector3f = NULL;
9479                         rsurface.modelnormal3f = NULL;
9480                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
9481                 }
9482                 rsurface.modelvertex3f_bufferobject = 0;
9483                 rsurface.modelvertex3f_bufferoffset = 0;
9484                 rsurface.modelsvector3f_bufferobject = 0;
9485                 rsurface.modelsvector3f_bufferoffset = 0;
9486                 rsurface.modeltvector3f_bufferobject = 0;
9487                 rsurface.modeltvector3f_bufferoffset = 0;
9488                 rsurface.modelnormal3f_bufferobject = 0;
9489                 rsurface.modelnormal3f_bufferoffset = 0;
9490                 rsurface.generatedvertex = true;
9491         }
9492         else
9493         {
9494                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
9495                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9496                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9497                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9498                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9499                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9500                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9501                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9502                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9503                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
9504                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9505                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9506                 rsurface.generatedvertex = false;
9507         }
9508         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
9509         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9510         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9511         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
9512         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9513         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9514         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
9515         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9516         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9517         rsurface.modelelement3i = model->surfmesh.data_element3i;
9518         rsurface.modelelement3s = model->surfmesh.data_element3s;
9519         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9520         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9521         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9522         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9523         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9524         rsurface.modelsurfaces = model->data_surfaces;
9525         rsurface.vertex3f  = rsurface.modelvertex3f;
9526         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9527         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9528         rsurface.svector3f = rsurface.modelsvector3f;
9529         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9530         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9531         rsurface.tvector3f = rsurface.modeltvector3f;
9532         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9533         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9534         rsurface.normal3f  = rsurface.modelnormal3f;
9535         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9536         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9537         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9538 }
9539
9540 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)
9541 {
9542         rsurface.entity = r_refdef.scene.worldentity;
9543         rsurface.skeleton = NULL;
9544         rsurface.ent_skinnum = 0;
9545         rsurface.ent_qwskin = -1;
9546         rsurface.ent_shadertime = shadertime;
9547         rsurface.ent_flags = entflags;
9548         rsurface.modelnum_vertices = numvertices;
9549         rsurface.modelnum_triangles = numtriangles;
9550         if (rsurface.array_size < rsurface.modelnum_vertices)
9551                 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
9552         rsurface.matrix = *matrix;
9553         rsurface.inversematrix = *inversematrix;
9554         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9555         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9556         R_EntityMatrix(&rsurface.matrix);
9557         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9558         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9559         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9560         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9561         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9562         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9563         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9564         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9565         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9566         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9567         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9568         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
9569         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);
9570         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9571         rsurface.frameblend[0].lerp = 1;
9572         rsurface.ent_alttextures = false;
9573         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9574         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9575         if (wanttangents)
9576         {
9577                 rsurface.modelvertex3f = vertex3f;
9578                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
9579                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
9580                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9581         }
9582         else if (wantnormals)
9583         {
9584                 rsurface.modelvertex3f = vertex3f;
9585                 rsurface.modelsvector3f = NULL;
9586                 rsurface.modeltvector3f = NULL;
9587                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9588         }
9589         else
9590         {
9591                 rsurface.modelvertex3f = vertex3f;
9592                 rsurface.modelsvector3f = NULL;
9593                 rsurface.modeltvector3f = NULL;
9594                 rsurface.modelnormal3f = NULL;
9595         }
9596         rsurface.modelvertex3f_bufferobject = 0;
9597         rsurface.modelvertex3f_bufferoffset = 0;
9598         rsurface.modelsvector3f_bufferobject = 0;
9599         rsurface.modelsvector3f_bufferoffset = 0;
9600         rsurface.modeltvector3f_bufferobject = 0;
9601         rsurface.modeltvector3f_bufferoffset = 0;
9602         rsurface.modelnormal3f_bufferobject = 0;
9603         rsurface.modelnormal3f_bufferoffset = 0;
9604         rsurface.generatedvertex = true;
9605         rsurface.modellightmapcolor4f  = color4f;
9606         rsurface.modellightmapcolor4f_bufferobject = 0;
9607         rsurface.modellightmapcolor4f_bufferoffset = 0;
9608         rsurface.modeltexcoordtexture2f  = texcoord2f;
9609         rsurface.modeltexcoordtexture2f_bufferobject = 0;
9610         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9611         rsurface.modeltexcoordlightmap2f  = NULL;
9612         rsurface.modeltexcoordlightmap2f_bufferobject = 0;
9613         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9614         rsurface.modelelement3i = element3i;
9615         rsurface.modelelement3s = element3s;
9616         rsurface.modelelement3i_bufferobject = 0;
9617         rsurface.modelelement3s_bufferobject = 0;
9618         rsurface.modellightmapoffsets = NULL;
9619         rsurface.modelsurfaces = NULL;
9620         rsurface.vertex3f  = rsurface.modelvertex3f;
9621         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9622         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9623         rsurface.svector3f = rsurface.modelsvector3f;
9624         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9625         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9626         rsurface.tvector3f = rsurface.modeltvector3f;
9627         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9628         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9629         rsurface.normal3f  = rsurface.modelnormal3f;
9630         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9631         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9632         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9633
9634         if (rsurface.modelnum_vertices && rsurface.modelelement3i)
9635         {
9636                 if ((wantnormals || wanttangents) && !normal3f)
9637                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9638                 if (wanttangents && !svector3f)
9639                         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);
9640         }
9641 }
9642
9643 float RSurf_FogPoint(const float *v)
9644 {
9645         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9646         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9647         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9648         float FogHeightFade = r_refdef.fogheightfade;
9649         float fogfrac;
9650         unsigned int fogmasktableindex;
9651         if (r_refdef.fogplaneviewabove)
9652                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9653         else
9654                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9655         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9656         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9657 }
9658
9659 float RSurf_FogVertex(const float *v)
9660 {
9661         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9662         float FogPlaneViewDist = rsurface.fogplaneviewdist;
9663         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9664         float FogHeightFade = rsurface.fogheightfade;
9665         float fogfrac;
9666         unsigned int fogmasktableindex;
9667         if (r_refdef.fogplaneviewabove)
9668                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9669         else
9670                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9671         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9672         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9673 }
9674
9675 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9676 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9677 {
9678         int deformindex;
9679         int texturesurfaceindex;
9680         int i, j;
9681         float amplitude;
9682         float animpos;
9683         float scale;
9684         const float *v1, *in_tc;
9685         float *out_tc;
9686         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9687         float waveparms[4];
9688         q3shaderinfo_deform_t *deform;
9689         // 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
9690         if (rsurface.generatedvertex)
9691         {
9692                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
9693                         generatenormals = true;
9694                 for (i = 0;i < Q3MAXDEFORMS;i++)
9695                 {
9696                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
9697                         {
9698                                 generatetangents = true;
9699                                 generatenormals = true;
9700                         }
9701                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
9702                                 generatenormals = true;
9703                 }
9704                 if (generatenormals && !rsurface.modelnormal3f)
9705                 {
9706                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9707                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
9708                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
9709                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9710                 }
9711                 if (generatetangents && !rsurface.modelsvector3f)
9712                 {
9713                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9714                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
9715                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
9716                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9717                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
9718                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
9719                         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);
9720                 }
9721         }
9722         rsurface.vertex3f  = rsurface.modelvertex3f;
9723         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9724         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9725         rsurface.svector3f = rsurface.modelsvector3f;
9726         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9727         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9728         rsurface.tvector3f = rsurface.modeltvector3f;
9729         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9730         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9731         rsurface.normal3f  = rsurface.modelnormal3f;
9732         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9733         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9734         // if vertices are deformed (sprite flares and things in maps, possibly
9735         // water waves, bulges and other deformations), generate them into
9736         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
9737         // (may be static model data or generated data for an animated model, or
9738         //  the previous deform pass)
9739         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
9740         {
9741                 switch (deform->deform)
9742                 {
9743                 default:
9744                 case Q3DEFORM_PROJECTIONSHADOW:
9745                 case Q3DEFORM_TEXT0:
9746                 case Q3DEFORM_TEXT1:
9747                 case Q3DEFORM_TEXT2:
9748                 case Q3DEFORM_TEXT3:
9749                 case Q3DEFORM_TEXT4:
9750                 case Q3DEFORM_TEXT5:
9751                 case Q3DEFORM_TEXT6:
9752                 case Q3DEFORM_TEXT7:
9753                 case Q3DEFORM_NONE:
9754                         break;
9755                 case Q3DEFORM_AUTOSPRITE:
9756                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9757                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9758                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9759                         VectorNormalize(newforward);
9760                         VectorNormalize(newright);
9761                         VectorNormalize(newup);
9762                         // make deformed versions of only the model vertices used by the specified surfaces
9763                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9764                         {
9765                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9766                                 // a single autosprite surface can contain multiple sprites...
9767                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9768                                 {
9769                                         VectorClear(center);
9770                                         for (i = 0;i < 4;i++)
9771                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9772                                         VectorScale(center, 0.25f, center);
9773                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
9774                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
9775                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
9776                                         for (i = 0;i < 4;i++)
9777                                         {
9778                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
9779                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9780                                         }
9781                                 }
9782                                 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);
9783                                 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);
9784                         }
9785                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9786                         rsurface.vertex3f_bufferobject = 0;
9787                         rsurface.vertex3f_bufferoffset = 0;
9788                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9789                         rsurface.svector3f_bufferobject = 0;
9790                         rsurface.svector3f_bufferoffset = 0;
9791                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9792                         rsurface.tvector3f_bufferobject = 0;
9793                         rsurface.tvector3f_bufferoffset = 0;
9794                         rsurface.normal3f = rsurface.array_deformednormal3f;
9795                         rsurface.normal3f_bufferobject = 0;
9796                         rsurface.normal3f_bufferoffset = 0;
9797                         break;
9798                 case Q3DEFORM_AUTOSPRITE2:
9799                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9800                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9801                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9802                         VectorNormalize(newforward);
9803                         VectorNormalize(newright);
9804                         VectorNormalize(newup);
9805                         // make deformed versions of only the model vertices used by the specified surfaces
9806                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9807                         {
9808                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9809                                 const float *v1, *v2;
9810                                 vec3_t start, end;
9811                                 float f, l;
9812                                 struct
9813                                 {
9814                                         float length2;
9815                                         const float *v1;
9816                                         const float *v2;
9817                                 }
9818                                 shortest[2];
9819                                 memset(shortest, 0, sizeof(shortest));
9820                                 // a single autosprite surface can contain multiple sprites...
9821                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9822                                 {
9823                                         VectorClear(center);
9824                                         for (i = 0;i < 4;i++)
9825                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9826                                         VectorScale(center, 0.25f, center);
9827                                         // find the two shortest edges, then use them to define the
9828                                         // axis vectors for rotating around the central axis
9829                                         for (i = 0;i < 6;i++)
9830                                         {
9831                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
9832                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
9833 #if 0
9834                                                 Debug_PolygonBegin(NULL, 0);
9835                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
9836                                                 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);
9837                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
9838                                                 Debug_PolygonEnd();
9839 #endif
9840                                                 l = VectorDistance2(v1, v2);
9841                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9842                                                 if (v1[2] != v2[2])
9843                                                         l += (1.0f / 1024.0f);
9844                                                 if (shortest[0].length2 > l || i == 0)
9845                                                 {
9846                                                         shortest[1] = shortest[0];
9847                                                         shortest[0].length2 = l;
9848                                                         shortest[0].v1 = v1;
9849                                                         shortest[0].v2 = v2;
9850                                                 }
9851                                                 else if (shortest[1].length2 > l || i == 1)
9852                                                 {
9853                                                         shortest[1].length2 = l;
9854                                                         shortest[1].v1 = v1;
9855                                                         shortest[1].v2 = v2;
9856                                                 }
9857                                         }
9858                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9859                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9860 #if 0
9861                                         Debug_PolygonBegin(NULL, 0);
9862                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
9863                                         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);
9864                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
9865                                         Debug_PolygonEnd();
9866 #endif
9867                                         // this calculates the right vector from the shortest edge
9868                                         // and the up vector from the edge midpoints
9869                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9870                                         VectorNormalize(right);
9871                                         VectorSubtract(end, start, up);
9872                                         VectorNormalize(up);
9873                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9874                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9875                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9876                                         VectorNegate(forward, forward);
9877                                         VectorReflect(forward, 0, up, forward);
9878                                         VectorNormalize(forward);
9879                                         CrossProduct(up, forward, newright);
9880                                         VectorNormalize(newright);
9881 #if 0
9882                                         Debug_PolygonBegin(NULL, 0);
9883                                         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);
9884                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
9885                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
9886                                         Debug_PolygonEnd();
9887 #endif
9888 #if 0
9889                                         Debug_PolygonBegin(NULL, 0);
9890                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
9891                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
9892                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
9893                                         Debug_PolygonEnd();
9894 #endif
9895                                         // rotate the quad around the up axis vector, this is made
9896                                         // especially easy by the fact we know the quad is flat,
9897                                         // so we only have to subtract the center position and
9898                                         // measure distance along the right vector, and then
9899                                         // multiply that by the newright vector and add back the
9900                                         // center position
9901                                         // we also need to subtract the old position to undo the
9902                                         // displacement from the center, which we do with a
9903                                         // DotProduct, the subtraction/addition of center is also
9904                                         // optimized into DotProducts here
9905                                         l = DotProduct(right, center);
9906                                         for (i = 0;i < 4;i++)
9907                                         {
9908                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
9909                                                 f = DotProduct(right, v1) - l;
9910                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9911                                         }
9912                                 }
9913                                 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);
9914                                 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);
9915                         }
9916                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9917                         rsurface.vertex3f_bufferobject = 0;
9918                         rsurface.vertex3f_bufferoffset = 0;
9919                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9920                         rsurface.svector3f_bufferobject = 0;
9921                         rsurface.svector3f_bufferoffset = 0;
9922                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9923                         rsurface.tvector3f_bufferobject = 0;
9924                         rsurface.tvector3f_bufferoffset = 0;
9925                         rsurface.normal3f = rsurface.array_deformednormal3f;
9926                         rsurface.normal3f_bufferobject = 0;
9927                         rsurface.normal3f_bufferoffset = 0;
9928                         break;
9929                 case Q3DEFORM_NORMAL:
9930                         // deform the normals to make reflections wavey
9931                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9932                         {
9933                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9934                                 for (j = 0;j < surface->num_vertices;j++)
9935                                 {
9936                                         float vertex[3];
9937                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
9938                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
9939                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
9940                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9941                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9942                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9943                                         VectorNormalize(normal);
9944                                 }
9945                                 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);
9946                         }
9947                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9948                         rsurface.svector3f_bufferobject = 0;
9949                         rsurface.svector3f_bufferoffset = 0;
9950                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9951                         rsurface.tvector3f_bufferobject = 0;
9952                         rsurface.tvector3f_bufferoffset = 0;
9953                         rsurface.normal3f = rsurface.array_deformednormal3f;
9954                         rsurface.normal3f_bufferobject = 0;
9955                         rsurface.normal3f_bufferoffset = 0;
9956                         break;
9957                 case Q3DEFORM_WAVE:
9958                         // deform vertex array to make wavey water and flags and such
9959                         waveparms[0] = deform->waveparms[0];
9960                         waveparms[1] = deform->waveparms[1];
9961                         waveparms[2] = deform->waveparms[2];
9962                         waveparms[3] = deform->waveparms[3];
9963                         // this is how a divisor of vertex influence on deformation
9964                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9965                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9966                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9967                         {
9968                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9969                                 for (j = 0;j < surface->num_vertices;j++)
9970                                 {
9971                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
9972                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9973                                         // if the wavefunc depends on time, evaluate it per-vertex
9974                                         if (waveparms[3])
9975                                         {
9976                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
9977                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9978                                         }
9979                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9980                                 }
9981                         }
9982                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9983                         rsurface.vertex3f_bufferobject = 0;
9984                         rsurface.vertex3f_bufferoffset = 0;
9985                         break;
9986                 case Q3DEFORM_BULGE:
9987                         // deform vertex array to make the surface have moving bulges
9988                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9989                         {
9990                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9991                                 for (j = 0;j < surface->num_vertices;j++)
9992                                 {
9993                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
9994                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9995                                 }
9996                         }
9997                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9998                         rsurface.vertex3f_bufferobject = 0;
9999                         rsurface.vertex3f_bufferoffset = 0;
10000                         break;
10001                 case Q3DEFORM_MOVE:
10002                         // deform vertex array
10003                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10004                         VectorScale(deform->parms, scale, waveparms);
10005                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10006                         {
10007                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10008                                 for (j = 0;j < surface->num_vertices;j++)
10009                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
10010                         }
10011                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
10012                         rsurface.vertex3f_bufferobject = 0;
10013                         rsurface.vertex3f_bufferoffset = 0;
10014                         break;
10015                 }
10016         }
10017         // generate texcoords based on the chosen texcoord source
10018         switch(rsurface.texture->tcgen.tcgen)
10019         {
10020         default:
10021         case Q3TCGEN_TEXTURE:
10022                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
10023                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
10024                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
10025                 break;
10026         case Q3TCGEN_LIGHTMAP:
10027                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
10028                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
10029                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
10030                 break;
10031         case Q3TCGEN_VECTOR:
10032                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10033                 {
10034                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10035                         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)
10036                         {
10037                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
10038                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
10039                         }
10040                 }
10041                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
10042                 rsurface.texcoordtexture2f_bufferobject  = 0;
10043                 rsurface.texcoordtexture2f_bufferoffset  = 0;
10044                 break;
10045         case Q3TCGEN_ENVIRONMENT:
10046                 // make environment reflections using a spheremap
10047                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10048                 {
10049                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10050                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
10051                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
10052                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
10053                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
10054                         {
10055                                 // identical to Q3A's method, but executed in worldspace so
10056                                 // carried models can be shiny too
10057
10058                                 float viewer[3], d, reflected[3], worldreflected[3];
10059
10060                                 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
10061                                 // VectorNormalize(viewer);
10062
10063                                 d = DotProduct(normal, viewer);
10064
10065                                 reflected[0] = normal[0]*2*d - viewer[0];
10066                                 reflected[1] = normal[1]*2*d - viewer[1];
10067                                 reflected[2] = normal[2]*2*d - viewer[2];
10068                                 // note: this is proportinal to viewer, so we can normalize later
10069
10070                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10071                                 VectorNormalize(worldreflected);
10072
10073                                 // note: this sphere map only uses world x and z!
10074                                 // so positive and negative y will LOOK THE SAME.
10075                                 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
10076                                 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
10077                         }
10078                 }
10079                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
10080                 rsurface.texcoordtexture2f_bufferobject  = 0;
10081                 rsurface.texcoordtexture2f_bufferoffset  = 0;
10082                 break;
10083         }
10084         // the only tcmod that needs software vertex processing is turbulent, so
10085         // check for it here and apply the changes if needed
10086         // and we only support that as the first one
10087         // (handling a mixture of turbulent and other tcmods would be problematic
10088         //  without punting it entirely to a software path)
10089         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10090         {
10091                 amplitude = rsurface.texture->tcmods[0].parms[1];
10092                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
10093                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10094                 {
10095                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10096                         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)
10097                         {
10098                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10099                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10100                         }
10101                 }
10102                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
10103                 rsurface.texcoordtexture2f_bufferobject  = 0;
10104                 rsurface.texcoordtexture2f_bufferoffset  = 0;
10105         }
10106         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
10107         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
10108         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
10109         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
10110 }
10111
10112 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10113 {
10114         int i, j;
10115         const msurface_t *surface = texturesurfacelist[0];
10116         const msurface_t *surface2;
10117         int firstvertex;
10118         int endvertex;
10119         int numvertices;
10120         int numtriangles;
10121         // TODO: lock all array ranges before render, rather than on each surface
10122         if (texturenumsurfaces == 1)
10123                 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);
10124         else if (r_batchmode.integer == 2)
10125         {
10126                 #define MAXBATCHTRIANGLES 4096
10127                 int batchtriangles = 0;
10128                 static int batchelements[MAXBATCHTRIANGLES*3];
10129                 for (i = 0;i < texturenumsurfaces;i = j)
10130                 {
10131                         surface = texturesurfacelist[i];
10132                         j = i + 1;
10133                         if (surface->num_triangles > MAXBATCHTRIANGLES)
10134                         {
10135                                 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);
10136                                 continue;
10137                         }
10138                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
10139                         batchtriangles = surface->num_triangles;
10140                         firstvertex = surface->num_firstvertex;
10141                         endvertex = surface->num_firstvertex + surface->num_vertices;
10142                         for (;j < texturenumsurfaces;j++)
10143                         {
10144                                 surface2 = texturesurfacelist[j];
10145                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
10146                                         break;
10147                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
10148                                 batchtriangles += surface2->num_triangles;
10149                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
10150                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
10151                         }
10152                         surface2 = texturesurfacelist[j-1];
10153                         numvertices = endvertex - firstvertex;
10154                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
10155                 }
10156         }
10157         else if (r_batchmode.integer == 1)
10158         {
10159                 for (i = 0;i < texturenumsurfaces;i = j)
10160                 {
10161                         surface = texturesurfacelist[i];
10162                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10163                                 if (texturesurfacelist[j] != surface2)
10164                                         break;
10165                         surface2 = texturesurfacelist[j-1];
10166                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
10167                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
10168                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10169                 }
10170         }
10171         else
10172         {
10173                 for (i = 0;i < texturenumsurfaces;i++)
10174                 {
10175                         surface = texturesurfacelist[i];
10176                         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);
10177                 }
10178         }
10179 }
10180
10181 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
10182 {
10183         switch(vid.renderpath)
10184         {
10185         case RENDERPATH_CGGL:
10186 #ifdef SUPPORTCG
10187                 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
10188                 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
10189 #endif
10190                 break;
10191         case RENDERPATH_GL20:
10192                 if (r_glsl_permutation->loc_Texture_Lightmap  >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
10193                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
10194                 break;
10195         case RENDERPATH_GL13:
10196         case RENDERPATH_GL11:
10197                 R_Mesh_TexBind(0, surface->lightmaptexture);
10198                 break;
10199         }
10200 }
10201
10202 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
10203 {
10204         // pick the closest matching water plane and bind textures
10205         int planeindex, vertexindex;
10206         float d, bestd;
10207         vec3_t vert;
10208         const float *v;
10209         r_waterstate_waterplane_t *p, *bestp;
10210         bestd = 0;
10211         bestp = NULL;
10212         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
10213         {
10214                 d = 0;
10215                 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
10216                 {
10217                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10218                         d += fabs(PlaneDiff(vert, &p->plane));
10219                 }
10220                 if (bestd > d || !bestp)
10221                 {
10222                         bestd = d;
10223                         bestp = p;
10224                 }
10225         }
10226         switch(vid.renderpath)
10227         {
10228         case RENDERPATH_CGGL:
10229 #ifdef SUPPORTCG
10230                 if (r_cg_permutation->fp_Texture_Refraction) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR
10231                 if (r_cg_permutation->fp_Texture_Reflection) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR
10232 #endif
10233                 break;
10234         case RENDERPATH_GL20:
10235                 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
10236                 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
10237                 break;
10238         case RENDERPATH_GL13:
10239         case RENDERPATH_GL11:
10240                 break;
10241         }
10242 }
10243
10244 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10245 {
10246         int i;
10247         const msurface_t *surface;
10248         if (r_waterstate.renderingscene)
10249                 return;
10250         for (i = 0;i < texturenumsurfaces;i++)
10251         {
10252                 surface = texturesurfacelist[i];
10253                 RSurf_BindLightmapForSurface(surface);
10254                 RSurf_BindReflectionForSurface(surface);
10255                 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);
10256         }
10257 }
10258
10259 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10260 {
10261         int i;
10262         int j;
10263         const msurface_t *surface = texturesurfacelist[0];
10264         const msurface_t *surface2;
10265         int firstvertex;
10266         int endvertex;
10267         int numvertices;
10268         int numtriangles;
10269         if (texturenumsurfaces == 1)
10270         {
10271                 RSurf_BindLightmapForSurface(surface);
10272                 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);
10273         }
10274         else if (r_batchmode.integer == 2)
10275         {
10276 #define MAXBATCHTRIANGLES 4096
10277                 int batchtriangles = 0;
10278                 static int batchelements[MAXBATCHTRIANGLES*3];
10279                 for (i = 0;i < texturenumsurfaces;i = j)
10280                 {
10281                         surface = texturesurfacelist[i];
10282                         RSurf_BindLightmapForSurface(surface);
10283                         j = i + 1;
10284                         if (surface->num_triangles > MAXBATCHTRIANGLES)
10285                         {
10286                                 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);
10287                                 continue;
10288                         }
10289                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
10290                         batchtriangles = surface->num_triangles;
10291                         firstvertex = surface->num_firstvertex;
10292                         endvertex = surface->num_firstvertex + surface->num_vertices;
10293                         for (;j < texturenumsurfaces;j++)
10294                         {
10295                                 surface2 = texturesurfacelist[j];
10296                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
10297                                         break;
10298                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
10299                                 batchtriangles += surface2->num_triangles;
10300                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
10301                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
10302                         }
10303                         surface2 = texturesurfacelist[j-1];
10304                         numvertices = endvertex - firstvertex;
10305                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
10306                 }
10307         }
10308         else if (r_batchmode.integer == 1)
10309         {
10310 #if 0
10311                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
10312                 for (i = 0;i < texturenumsurfaces;i = j)
10313                 {
10314                         surface = texturesurfacelist[i];
10315                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10316                                 if (texturesurfacelist[j] != surface2)
10317                                         break;
10318                         Con_Printf(" %i", j - i);
10319                 }
10320                 Con_Printf("\n");
10321                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
10322 #endif
10323                 for (i = 0;i < texturenumsurfaces;i = j)
10324                 {
10325                         surface = texturesurfacelist[i];
10326                         RSurf_BindLightmapForSurface(surface);
10327                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10328                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
10329                                         break;
10330 #if 0
10331                         Con_Printf(" %i", j - i);
10332 #endif
10333                         surface2 = texturesurfacelist[j-1];
10334                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
10335                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
10336                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10337                 }
10338 #if 0
10339                 Con_Printf("\n");
10340 #endif
10341         }
10342         else
10343         {
10344                 for (i = 0;i < texturenumsurfaces;i++)
10345                 {
10346                         surface = texturesurfacelist[i];
10347                         RSurf_BindLightmapForSurface(surface);
10348                         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);
10349                 }
10350         }
10351 }
10352
10353 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10354 {
10355         int j;
10356         int texturesurfaceindex;
10357         if (r_showsurfaces.integer == 2)
10358         {
10359                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10360                 {
10361                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10362                         for (j = 0;j < surface->num_triangles;j++)
10363                         {
10364                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
10365                                 GL_Color(f, f, f, 1);
10366                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10367                         }
10368                 }
10369         }
10370         else
10371         {
10372                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10373                 {
10374                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10375                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
10376                         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);
10377                         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);
10378                 }
10379         }
10380 }
10381
10382 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10383 {
10384         int texturesurfaceindex;
10385         int i;
10386         const float *v;
10387         float *c2;
10388         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10389         {
10390                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10391                 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)
10392                 {
10393                         c2[0] = 0.5;
10394                         c2[1] = 0.5;
10395                         c2[2] = 0.5;
10396                         c2[3] = 1;
10397                 }
10398         }
10399         rsurface.lightmapcolor4f = rsurface.array_color4f;
10400         rsurface.lightmapcolor4f_bufferobject = 0;
10401         rsurface.lightmapcolor4f_bufferoffset = 0;
10402 }
10403
10404 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10405 {
10406         int texturesurfaceindex;
10407         int i;
10408         float f;
10409         const float *v;
10410         const float *c;
10411         float *c2;
10412         if (rsurface.lightmapcolor4f)
10413         {
10414                 // generate color arrays for the surfaces in this list
10415                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10416                 {
10417                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10418                         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)
10419                         {
10420                                 f = RSurf_FogVertex(v);
10421                                 c2[0] = c[0] * f;
10422                                 c2[1] = c[1] * f;
10423                                 c2[2] = c[2] * f;
10424                                 c2[3] = c[3];
10425                         }
10426                 }
10427         }
10428         else
10429         {
10430                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10431                 {
10432                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10433                         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)
10434                         {
10435                                 f = RSurf_FogVertex(v);
10436                                 c2[0] = f;
10437                                 c2[1] = f;
10438                                 c2[2] = f;
10439                                 c2[3] = 1;
10440                         }
10441                 }
10442         }
10443         rsurface.lightmapcolor4f = rsurface.array_color4f;
10444         rsurface.lightmapcolor4f_bufferobject = 0;
10445         rsurface.lightmapcolor4f_bufferoffset = 0;
10446 }
10447
10448 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10449 {
10450         int texturesurfaceindex;
10451         int i;
10452         float f;
10453         const float *v;
10454         const float *c;
10455         float *c2;
10456         if (!rsurface.lightmapcolor4f)
10457                 return;
10458         // generate color arrays for the surfaces in this list
10459         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10460         {
10461                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10462                 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)
10463                 {
10464                         f = RSurf_FogVertex(v);
10465                         c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10466                         c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10467                         c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10468                         c2[3] = c[3];
10469                 }
10470         }
10471         rsurface.lightmapcolor4f = rsurface.array_color4f;
10472         rsurface.lightmapcolor4f_bufferobject = 0;
10473         rsurface.lightmapcolor4f_bufferoffset = 0;
10474 }
10475
10476 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
10477 {
10478         int texturesurfaceindex;
10479         int i;
10480         const float *c;
10481         float *c2;
10482         if (!rsurface.lightmapcolor4f)
10483                 return;
10484         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10485         {
10486                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10487                 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)
10488                 {
10489                         c2[0] = c[0] * r;
10490                         c2[1] = c[1] * g;
10491                         c2[2] = c[2] * b;
10492                         c2[3] = c[3] * a;
10493                 }
10494         }
10495         rsurface.lightmapcolor4f = rsurface.array_color4f;
10496         rsurface.lightmapcolor4f_bufferobject = 0;
10497         rsurface.lightmapcolor4f_bufferoffset = 0;
10498 }
10499
10500 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10501 {
10502         int texturesurfaceindex;
10503         int i;
10504         const float *c;
10505         float *c2;
10506         if (!rsurface.lightmapcolor4f)
10507                 return;
10508         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10509         {
10510                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10511                 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)
10512                 {
10513                         c2[0] = c[0] + r_refdef.scene.ambient;
10514                         c2[1] = c[1] + r_refdef.scene.ambient;
10515                         c2[2] = c[2] + r_refdef.scene.ambient;
10516                         c2[3] = c[3];
10517                 }
10518         }
10519         rsurface.lightmapcolor4f = rsurface.array_color4f;
10520         rsurface.lightmapcolor4f_bufferobject = 0;
10521         rsurface.lightmapcolor4f_bufferoffset = 0;
10522 }
10523
10524 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10525 {
10526         // TODO: optimize
10527         rsurface.lightmapcolor4f = NULL;
10528         rsurface.lightmapcolor4f_bufferobject = 0;
10529         rsurface.lightmapcolor4f_bufferoffset = 0;
10530         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10531         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10532         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10533         GL_Color(r, g, b, a);
10534         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10535 }
10536
10537 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10538 {
10539         // TODO: optimize applyfog && applycolor case
10540         // just apply fog if necessary, and tint the fog color array if necessary
10541         rsurface.lightmapcolor4f = NULL;
10542         rsurface.lightmapcolor4f_bufferobject = 0;
10543         rsurface.lightmapcolor4f_bufferoffset = 0;
10544         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10545         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10546         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10547         GL_Color(r, g, b, a);
10548         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10549 }
10550
10551 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10552 {
10553         int texturesurfaceindex;
10554         int i;
10555         float *c;
10556         // TODO: optimize
10557         if (texturesurfacelist[0]->lightmapinfo)
10558         {
10559                 // generate color arrays for the surfaces in this list
10560                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10561                 {
10562                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10563                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
10564                         {
10565                                 if (surface->lightmapinfo->samples)
10566                                 {
10567                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
10568                                         float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
10569                                         VectorScale(lm, scale, c);
10570                                         if (surface->lightmapinfo->styles[1] != 255)
10571                                         {
10572                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
10573                                                 lm += size3;
10574                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
10575                                                 VectorMA(c, scale, lm, c);
10576                                                 if (surface->lightmapinfo->styles[2] != 255)
10577                                                 {
10578                                                         lm += size3;
10579                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
10580                                                         VectorMA(c, scale, lm, c);
10581                                                         if (surface->lightmapinfo->styles[3] != 255)
10582                                                         {
10583                                                                 lm += size3;
10584                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
10585                                                                 VectorMA(c, scale, lm, c);
10586                                                         }
10587                                                 }
10588                                         }
10589                                 }
10590                                 else
10591                                         VectorClear(c);
10592                                 c[3] = 1;
10593                         }
10594                 }
10595                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10596                 rsurface.lightmapcolor4f_bufferobject = 0;
10597                 rsurface.lightmapcolor4f_bufferoffset = 0;
10598         }
10599         else
10600         {
10601                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10602                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10603                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10604         }
10605         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10606         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10607         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10608         GL_Color(r, g, b, a);
10609         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10610 }
10611
10612 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
10613 {
10614         int texturesurfaceindex;
10615         int i;
10616         float f;
10617         float alpha;
10618         const float *v;
10619         const float *n;
10620         float *c;
10621         vec3_t ambientcolor;
10622         vec3_t diffusecolor;
10623         vec3_t lightdir;
10624         // TODO: optimize
10625         // model lighting
10626         VectorCopy(rsurface.modellight_lightdir, lightdir);
10627         f = 0.5f * r_refdef.lightmapintensity;
10628         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10629         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10630         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10631         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10632         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10633         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10634         alpha = *a;
10635         if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
10636         {
10637                 // generate color arrays for the surfaces in this list
10638                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10639                 {
10640                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10641                         int numverts = surface->num_vertices;
10642                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
10643                         n = rsurface.normal3f + 3 * surface->num_firstvertex;
10644                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
10645                         // q3-style directional shading
10646                         for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
10647                         {
10648                                 if ((f = DotProduct(n, lightdir)) > 0)
10649                                         VectorMA(ambientcolor, f, diffusecolor, c);
10650                                 else
10651                                         VectorCopy(ambientcolor, c);
10652                                 c[3] = alpha;
10653                         }
10654                 }
10655                 *r = 1;
10656                 *g = 1;
10657                 *b = 1;
10658                 *a = 1;
10659                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10660                 rsurface.lightmapcolor4f_bufferobject = 0;
10661                 rsurface.lightmapcolor4f_bufferoffset = 0;
10662                 *applycolor = false;
10663         }
10664         else
10665         {
10666                 *r = ambientcolor[0];
10667                 *g = ambientcolor[1];
10668                 *b = ambientcolor[2];
10669                 rsurface.lightmapcolor4f = NULL;
10670                 rsurface.lightmapcolor4f_bufferobject = 0;
10671                 rsurface.lightmapcolor4f_bufferoffset = 0;
10672         }
10673 }
10674
10675 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10676 {
10677         RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
10678         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10679         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10680         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10681         GL_Color(r, g, b, a);
10682         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10683 }
10684
10685 void RSurf_SetupDepthAndCulling(void)
10686 {
10687         // submodels are biased to avoid z-fighting with world surfaces that they
10688         // may be exactly overlapping (avoids z-fighting artifacts on certain
10689         // doors and things in Quake maps)
10690         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10691         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10692         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10693         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10694 }
10695
10696 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10697 {
10698         // transparent sky would be ridiculous
10699         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10700                 return;
10701         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10702         skyrenderlater = true;
10703         RSurf_SetupDepthAndCulling();
10704         GL_DepthMask(true);
10705         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10706         // skymasking on them, and Quake3 never did sky masking (unlike
10707         // software Quake and software Quake2), so disable the sky masking
10708         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10709         // and skymasking also looks very bad when noclipping outside the
10710         // level, so don't use it then either.
10711         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
10712         {
10713                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10714                 R_Mesh_ColorPointer(NULL, 0, 0);
10715                 R_Mesh_ResetTextureState();
10716                 if (skyrendermasked)
10717                 {
10718                         R_SetupShader_DepthOrShadow();
10719                         // depth-only (masking)
10720                         GL_ColorMask(0,0,0,0);
10721                         // just to make sure that braindead drivers don't draw
10722                         // anything despite that colormask...
10723                         GL_BlendFunc(GL_ZERO, GL_ONE);
10724                 }
10725                 else
10726                 {
10727                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10728                         // fog sky
10729                         GL_BlendFunc(GL_ONE, GL_ZERO);
10730                 }
10731                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10732                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10733                 if (skyrendermasked)
10734                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10735         }
10736         R_Mesh_ResetTextureState();
10737         GL_Color(1, 1, 1, 1);
10738 }
10739
10740 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10741 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10742 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10743 {
10744         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
10745                 return;
10746         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10747         if (prepass)
10748         {
10749                 // render screenspace normalmap to texture
10750                 GL_DepthMask(true);
10751                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY);
10752                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10753         }
10754         else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !r_waterstate.renderingscene)
10755         {
10756                 // render water or distortion background, then blend surface on top
10757                 GL_DepthMask(true);
10758                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
10759                 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10760                 GL_DepthMask(false);
10761                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
10762                 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10763                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10764                 else
10765                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10766         }
10767         else
10768         {
10769                 // render surface normally
10770                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10771                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
10772                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
10773                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10774                 else if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10775                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10776                 else
10777                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10778         }
10779 }
10780
10781 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10782 {
10783         // OpenGL 1.3 path - anything not completely ancient
10784         int texturesurfaceindex;
10785         qboolean applycolor;
10786         qboolean applyfog;
10787         int layerindex;
10788         const texturelayer_t *layer;
10789         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10790
10791         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10792         {
10793                 vec4_t layercolor;
10794                 int layertexrgbscale;
10795                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10796                 {
10797                         if (layerindex == 0)
10798                                 GL_AlphaTest(true);
10799                         else
10800                         {
10801                                 GL_AlphaTest(false);
10802                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10803                         }
10804                 }
10805                 GL_DepthMask(layer->depthmask && writedepth);
10806                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10807                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10808                 {
10809                         layertexrgbscale = 4;
10810                         VectorScale(layer->color, 0.25f, layercolor);
10811                 }
10812                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10813                 {
10814                         layertexrgbscale = 2;
10815                         VectorScale(layer->color, 0.5f, layercolor);
10816                 }
10817                 else
10818                 {
10819                         layertexrgbscale = 1;
10820                         VectorScale(layer->color, 1.0f, layercolor);
10821                 }
10822                 layercolor[3] = layer->color[3];
10823                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10824                 R_Mesh_ColorPointer(NULL, 0, 0);
10825                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10826                 switch (layer->type)
10827                 {
10828                 case TEXTURELAYERTYPE_LITTEXTURE:
10829                         // single-pass lightmapped texture with 2x rgbscale
10830                         R_Mesh_TexBind(0, r_texture_white);
10831                         R_Mesh_TexMatrix(0, NULL);
10832                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10833                         R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10834                         R_Mesh_TexBind(1, layer->texture);
10835                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10836                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10837                         R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10838                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10839                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10840                         else if (rsurface.uselightmaptexture)
10841                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10842                         else
10843                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10844                         break;
10845                 case TEXTURELAYERTYPE_TEXTURE:
10846                         // singletexture unlit texture with transparency support
10847                         R_Mesh_TexBind(0, layer->texture);
10848                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10849                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10850                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10851                         R_Mesh_TexBind(1, 0);
10852                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10853                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10854                         break;
10855                 case TEXTURELAYERTYPE_FOG:
10856                         // singletexture fogging
10857                         if (layer->texture)
10858                         {
10859                                 R_Mesh_TexBind(0, layer->texture);
10860                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10861                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10862                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10863                         }
10864                         else
10865                         {
10866                                 R_Mesh_TexBind(0, 0);
10867                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10868                         }
10869                         R_Mesh_TexBind(1, 0);
10870                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10871                         // generate a color array for the fog pass
10872                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10873                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10874                         {
10875                                 int i;
10876                                 float f;
10877                                 const float *v;
10878                                 float *c;
10879                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10880                                 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)
10881                                 {
10882                                         f = 1 - RSurf_FogVertex(v);
10883                                         c[0] = layercolor[0];
10884                                         c[1] = layercolor[1];
10885                                         c[2] = layercolor[2];
10886                                         c[3] = f * layercolor[3];
10887                                 }
10888                         }
10889                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10890                         break;
10891                 default:
10892                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10893                 }
10894         }
10895         CHECKGLERROR
10896         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10897         {
10898                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10899                 GL_AlphaTest(false);
10900         }
10901 }
10902
10903 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10904 {
10905         // OpenGL 1.1 - crusty old voodoo path
10906         int texturesurfaceindex;
10907         qboolean applyfog;
10908         int layerindex;
10909         const texturelayer_t *layer;
10910         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10911
10912         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10913         {
10914                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10915                 {
10916                         if (layerindex == 0)
10917                                 GL_AlphaTest(true);
10918                         else
10919                         {
10920                                 GL_AlphaTest(false);
10921                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10922                         }
10923                 }
10924                 GL_DepthMask(layer->depthmask && writedepth);
10925                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10926                 R_Mesh_ColorPointer(NULL, 0, 0);
10927                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10928                 switch (layer->type)
10929                 {
10930                 case TEXTURELAYERTYPE_LITTEXTURE:
10931                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10932                         {
10933                                 // two-pass lit texture with 2x rgbscale
10934                                 // first the lightmap pass
10935                                 R_Mesh_TexBind(0, r_texture_white);
10936                                 R_Mesh_TexMatrix(0, NULL);
10937                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10938                                 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10939                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10940                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10941                                 else if (rsurface.uselightmaptexture)
10942                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10943                                 else
10944                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10945                                 // then apply the texture to it
10946                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10947                                 R_Mesh_TexBind(0, layer->texture);
10948                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10949                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10950                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10951                                 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);
10952                         }
10953                         else
10954                         {
10955                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10956                                 R_Mesh_TexBind(0, layer->texture);
10957                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10958                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10959                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10960                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10961                                         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);
10962                                 else
10963                                         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);
10964                         }
10965                         break;
10966                 case TEXTURELAYERTYPE_TEXTURE:
10967                         // singletexture unlit texture with transparency support
10968                         R_Mesh_TexBind(0, layer->texture);
10969                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10970                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10971                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10972                         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);
10973                         break;
10974                 case TEXTURELAYERTYPE_FOG:
10975                         // singletexture fogging
10976                         if (layer->texture)
10977                         {
10978                                 R_Mesh_TexBind(0, layer->texture);
10979                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10980                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10981                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10982                         }
10983                         else
10984                         {
10985                                 R_Mesh_TexBind(0, 0);
10986                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10987                         }
10988                         // generate a color array for the fog pass
10989                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10990                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10991                         {
10992                                 int i;
10993                                 float f;
10994                                 const float *v;
10995                                 float *c;
10996                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10997                                 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)
10998                                 {
10999                                         f = 1 - RSurf_FogVertex(v);
11000                                         c[0] = layer->color[0];
11001                                         c[1] = layer->color[1];
11002                                         c[2] = layer->color[2];
11003                                         c[3] = f * layer->color[3];
11004                                 }
11005                         }
11006                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11007                         break;
11008                 default:
11009                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11010                 }
11011         }
11012         CHECKGLERROR
11013         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11014         {
11015                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
11016                 GL_AlphaTest(false);
11017         }
11018 }
11019
11020 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11021 {
11022         float c[4];
11023
11024         GL_AlphaTest(false);
11025         R_Mesh_ColorPointer(NULL, 0, 0);
11026         R_Mesh_ResetTextureState();
11027         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11028
11029         if(rsurface.texture && rsurface.texture->currentskinframe)
11030         {
11031                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11032                 c[3] *= rsurface.texture->currentalpha;
11033         }
11034         else
11035         {
11036                 c[0] = 1;
11037                 c[1] = 0;
11038                 c[2] = 1;
11039                 c[3] = 1;
11040         }
11041
11042         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11043         {
11044                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11045                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11046                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11047         }
11048
11049         // brighten it up (as texture value 127 means "unlit")
11050         c[0] *= 2 * r_refdef.view.colorscale;
11051         c[1] *= 2 * r_refdef.view.colorscale;
11052         c[2] *= 2 * r_refdef.view.colorscale;
11053
11054         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11055                 c[3] *= r_wateralpha.value;
11056
11057         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11058         {
11059                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11060                 GL_DepthMask(false);
11061         }
11062         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11063         {
11064                 GL_BlendFunc(GL_ONE, GL_ONE);
11065                 GL_DepthMask(false);
11066         }
11067         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11068         {
11069                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11070                 GL_DepthMask(false);
11071         }
11072         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11073         {
11074                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11075                 GL_DepthMask(false);
11076         }
11077         else
11078         {
11079                 GL_BlendFunc(GL_ONE, GL_ZERO);
11080                 GL_DepthMask(writedepth);
11081         }
11082
11083         rsurface.lightmapcolor4f = NULL;
11084
11085         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11086         {
11087                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11088
11089                 rsurface.lightmapcolor4f = NULL;
11090                 rsurface.lightmapcolor4f_bufferobject = 0;
11091                 rsurface.lightmapcolor4f_bufferoffset = 0;
11092         }
11093         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11094         {
11095                 qboolean applycolor = true;
11096                 float one = 1.0;
11097
11098                 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
11099
11100                 r_refdef.lightmapintensity = 1;
11101                 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
11102                 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11103         }
11104         else
11105         {
11106                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11107
11108                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
11109                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
11110                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11111         }
11112
11113         if(!rsurface.lightmapcolor4f)
11114                 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
11115
11116         RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
11117         RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
11118         if(r_refdef.fogenabled)
11119                 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
11120
11121         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
11122         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11123 }
11124
11125 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11126 {
11127         CHECKGLERROR
11128         RSurf_SetupDepthAndCulling();
11129         if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
11130         {
11131                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
11132                 return;
11133         }
11134         switch (vid.renderpath)
11135         {
11136         case RENDERPATH_GL20:
11137         case RENDERPATH_CGGL:
11138                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11139                 break;
11140         case RENDERPATH_GL13:
11141                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11142                 break;
11143         case RENDERPATH_GL11:
11144                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11145                 break;
11146         }
11147         CHECKGLERROR
11148 }
11149
11150 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11151 {
11152         CHECKGLERROR
11153         RSurf_SetupDepthAndCulling();
11154         if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
11155         {
11156                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
11157                 return;
11158         }
11159         switch (vid.renderpath)
11160         {
11161         case RENDERPATH_GL20:
11162         case RENDERPATH_CGGL:
11163                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11164                 break;
11165         case RENDERPATH_GL13:
11166                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11167                 break;
11168         case RENDERPATH_GL11:
11169                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11170                 break;
11171         }
11172         CHECKGLERROR
11173 }
11174
11175 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11176 {
11177         int i, j;
11178         int texturenumsurfaces, endsurface;
11179         texture_t *texture;
11180         const msurface_t *surface;
11181         const msurface_t *texturesurfacelist[256];
11182
11183         // if the model is static it doesn't matter what value we give for
11184         // wantnormals and wanttangents, so this logic uses only rules applicable
11185         // to a model, knowing that they are meaningless otherwise
11186         if (ent == r_refdef.scene.worldentity)
11187                 RSurf_ActiveWorldEntity();
11188         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11189                 RSurf_ActiveModelEntity(ent, false, false, false);
11190         else
11191         {
11192                 switch (vid.renderpath)
11193                 {
11194                 case RENDERPATH_GL20:
11195                 case RENDERPATH_CGGL:
11196                         RSurf_ActiveModelEntity(ent, true, true, false);
11197                         break;
11198                 case RENDERPATH_GL13:
11199                 case RENDERPATH_GL11:
11200                         RSurf_ActiveModelEntity(ent, true, false, false);
11201                         break;
11202                 }
11203         }
11204
11205         if (r_transparentdepthmasking.integer)
11206         {
11207                 qboolean setup = false;
11208                 for (i = 0;i < numsurfaces;i = j)
11209                 {
11210                         j = i + 1;
11211                         surface = rsurface.modelsurfaces + surfacelist[i];
11212                         texture = surface->texture;
11213                         rsurface.texture = R_GetCurrentTexture(texture);
11214                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11215                         // scan ahead until we find a different texture
11216                         endsurface = min(i + 1024, numsurfaces);
11217                         texturenumsurfaces = 0;
11218                         texturesurfacelist[texturenumsurfaces++] = surface;
11219                         for (;j < endsurface;j++)
11220                         {
11221                                 surface = rsurface.modelsurfaces + surfacelist[j];
11222                                 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
11223                                         break;
11224                                 texturesurfacelist[texturenumsurfaces++] = surface;
11225                         }
11226                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11227                                 continue;
11228                         // render the range of surfaces as depth
11229                         if (!setup)
11230                         {
11231                                 setup = true;
11232                                 GL_ColorMask(0,0,0,0);
11233                                 GL_Color(1,1,1,1);
11234                                 GL_DepthTest(true);
11235                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11236                                 GL_DepthMask(true);
11237                                 GL_AlphaTest(false);
11238                                 R_Mesh_ColorPointer(NULL, 0, 0);
11239                                 R_Mesh_ResetTextureState();
11240                                 R_SetupShader_DepthOrShadow();
11241                         }
11242                         RSurf_SetupDepthAndCulling();
11243                         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11244                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11245                 }
11246                 if (setup)
11247                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11248         }
11249
11250         for (i = 0;i < numsurfaces;i = j)
11251         {
11252                 j = i + 1;
11253                 surface = rsurface.modelsurfaces + surfacelist[i];
11254                 texture = surface->texture;
11255                 rsurface.texture = R_GetCurrentTexture(texture);
11256                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11257                 // scan ahead until we find a different texture
11258                 endsurface = min(i + 1024, numsurfaces);
11259                 texturenumsurfaces = 0;
11260                 texturesurfacelist[texturenumsurfaces++] = surface;
11261                 for (;j < endsurface;j++)
11262                 {
11263                         surface = rsurface.modelsurfaces + surfacelist[j];
11264                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
11265                                 break;
11266                         texturesurfacelist[texturenumsurfaces++] = surface;
11267                 }
11268                 // render the range of surfaces
11269                 if (ent == r_refdef.scene.worldentity)
11270                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11271                 else
11272                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11273         }
11274         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11275         GL_AlphaTest(false);
11276 }
11277
11278 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
11279 {
11280         // transparent surfaces get pushed off into the transparent queue
11281         int surfacelistindex;
11282         const msurface_t *surface;
11283         vec3_t tempcenter, center;
11284         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11285         {
11286                 surface = texturesurfacelist[surfacelistindex];
11287                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11288                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11289                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11290                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11291                 if (queueentity->transparent_offset) // transparent offset
11292                 {
11293                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
11294                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
11295                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
11296                 }
11297                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
11298         }
11299 }
11300
11301 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11302 {
11303         const entity_render_t *queueentity = r_refdef.scene.worldentity;
11304         CHECKGLERROR
11305         if (depthonly)
11306         {
11307                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11308                         return;
11309                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11310                         return;
11311                 RSurf_SetupDepthAndCulling();
11312                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11313                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11314         }
11315         else if (prepass)
11316         {
11317                 if (!rsurface.texture->currentnumlayers)
11318                         return;
11319                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11320                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11321                 else
11322                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11323         }
11324         else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
11325         {
11326                 RSurf_SetupDepthAndCulling();
11327                 GL_AlphaTest(false);
11328                 R_Mesh_ColorPointer(NULL, 0, 0);
11329                 R_Mesh_ResetTextureState();
11330                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11331                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11332                 GL_DepthMask(true);
11333                 GL_BlendFunc(GL_ONE, GL_ZERO);
11334                 GL_Color(0, 0, 0, 1);
11335                 GL_DepthTest(writedepth);
11336                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11337         }
11338         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
11339         {
11340                 RSurf_SetupDepthAndCulling();
11341                 GL_AlphaTest(false);
11342                 R_Mesh_ColorPointer(NULL, 0, 0);
11343                 R_Mesh_ResetTextureState();
11344                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11345                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11346                 GL_DepthMask(true);
11347                 GL_BlendFunc(GL_ONE, GL_ZERO);
11348                 GL_DepthTest(true);
11349                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11350         }
11351         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11352                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11353         else if (!rsurface.texture->currentnumlayers)
11354                 return;
11355         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11356         {
11357                 // in the deferred case, transparent surfaces were queued during prepass
11358                 if (!r_shadow_usingdeferredprepass)
11359                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11360         }
11361         else
11362         {
11363                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11364                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11365         }
11366         CHECKGLERROR
11367 }
11368
11369 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11370 {
11371         int i, j;
11372         texture_t *texture;
11373         // break the surface list down into batches by texture and use of lightmapping
11374         for (i = 0;i < numsurfaces;i = j)
11375         {
11376                 j = i + 1;
11377                 // texture is the base texture pointer, rsurface.texture is the
11378                 // current frame/skin the texture is directing us to use (for example
11379                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11380                 // use skin 1 instead)
11381                 texture = surfacelist[i]->texture;
11382                 rsurface.texture = R_GetCurrentTexture(texture);
11383                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11384                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11385                 {
11386                         // if this texture is not the kind we want, skip ahead to the next one
11387                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11388                                 ;
11389                         continue;
11390                 }
11391                 // simply scan ahead until we find a different texture or lightmap state
11392                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11393                         ;
11394                 // render the range of surfaces
11395                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11396         }
11397 }
11398
11399 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
11400 {
11401         CHECKGLERROR
11402         if (depthonly)
11403         {
11404                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11405                         return;
11406                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11407                         return;
11408                 RSurf_SetupDepthAndCulling();
11409                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11410                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11411         }
11412         else if (prepass)
11413         {
11414                 if (!rsurface.texture->currentnumlayers)
11415                         return;
11416                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11417                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11418                 else
11419                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11420         }
11421         else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
11422         {
11423                 RSurf_SetupDepthAndCulling();
11424                 GL_AlphaTest(false);
11425                 R_Mesh_ColorPointer(NULL, 0, 0);
11426                 R_Mesh_ResetTextureState();
11427                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11428                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11429                 GL_DepthMask(true);
11430                 GL_BlendFunc(GL_ONE, GL_ZERO);
11431                 GL_Color(0, 0, 0, 1);
11432                 GL_DepthTest(writedepth);
11433                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11434         }
11435         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11436         {
11437                 RSurf_SetupDepthAndCulling();
11438                 GL_AlphaTest(false);
11439                 R_Mesh_ColorPointer(NULL, 0, 0);
11440                 R_Mesh_ResetTextureState();
11441                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11442                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11443                 GL_DepthMask(true);
11444                 GL_BlendFunc(GL_ONE, GL_ZERO);
11445                 GL_DepthTest(true);
11446                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11447         }
11448         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11449                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11450         else if (!rsurface.texture->currentnumlayers)
11451                 return;
11452         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11453         {
11454                 // in the deferred case, transparent surfaces were queued during prepass
11455                 if (!r_shadow_usingdeferredprepass)
11456                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11457         }
11458         else
11459         {
11460                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11461                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11462         }
11463         CHECKGLERROR
11464 }
11465
11466 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11467 {
11468         int i, j;
11469         texture_t *texture;
11470         // break the surface list down into batches by texture and use of lightmapping
11471         for (i = 0;i < numsurfaces;i = j)
11472         {
11473                 j = i + 1;
11474                 // texture is the base texture pointer, rsurface.texture is the
11475                 // current frame/skin the texture is directing us to use (for example
11476                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11477                 // use skin 1 instead)
11478                 texture = surfacelist[i]->texture;
11479                 rsurface.texture = R_GetCurrentTexture(texture);
11480                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11481                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11482                 {
11483                         // if this texture is not the kind we want, skip ahead to the next one
11484                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11485                                 ;
11486                         continue;
11487                 }
11488                 // simply scan ahead until we find a different texture or lightmap state
11489                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11490                         ;
11491                 // render the range of surfaces
11492                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
11493         }
11494 }
11495
11496 float locboxvertex3f[6*4*3] =
11497 {
11498         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11499         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11500         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11501         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11502         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11503         1,0,0, 0,0,0, 0,1,0, 1,1,0
11504 };
11505
11506 unsigned short locboxelements[6*2*3] =
11507 {
11508          0, 1, 2, 0, 2, 3,
11509          4, 5, 6, 4, 6, 7,
11510          8, 9,10, 8,10,11,
11511         12,13,14, 12,14,15,
11512         16,17,18, 16,18,19,
11513         20,21,22, 20,22,23
11514 };
11515
11516 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11517 {
11518         int i, j;
11519         cl_locnode_t *loc = (cl_locnode_t *)ent;
11520         vec3_t mins, size;
11521         float vertex3f[6*4*3];
11522         CHECKGLERROR
11523         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11524         GL_DepthMask(false);
11525         GL_DepthRange(0, 1);
11526         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11527         GL_DepthTest(true);
11528         GL_CullFace(GL_NONE);
11529         R_EntityMatrix(&identitymatrix);
11530
11531         R_Mesh_VertexPointer(vertex3f, 0, 0);
11532         R_Mesh_ColorPointer(NULL, 0, 0);
11533         R_Mesh_ResetTextureState();
11534         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11535
11536         i = surfacelist[0];
11537         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11538                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11539                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11540                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11541
11542         if (VectorCompare(loc->mins, loc->maxs))
11543         {
11544                 VectorSet(size, 2, 2, 2);
11545                 VectorMA(loc->mins, -0.5f, size, mins);
11546         }
11547         else
11548         {
11549                 VectorCopy(loc->mins, mins);
11550                 VectorSubtract(loc->maxs, loc->mins, size);
11551         }
11552
11553         for (i = 0;i < 6*4*3;)
11554                 for (j = 0;j < 3;j++, i++)
11555                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11556
11557         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
11558 }
11559
11560 void R_DrawLocs(void)
11561 {
11562         int index;
11563         cl_locnode_t *loc, *nearestloc;
11564         vec3_t center;
11565         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11566         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11567         {
11568                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11569                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11570         }
11571 }
11572
11573 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11574 {
11575         if (decalsystem->decals)
11576                 Mem_Free(decalsystem->decals);
11577         memset(decalsystem, 0, sizeof(*decalsystem));
11578 }
11579
11580 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)
11581 {
11582         tridecal_t *decal;
11583         tridecal_t *decals;
11584         int i;
11585
11586         // expand or initialize the system
11587         if (decalsystem->maxdecals <= decalsystem->numdecals)
11588         {
11589                 decalsystem_t old = *decalsystem;
11590                 qboolean useshortelements;
11591                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11592                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11593                 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)));
11594                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11595                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11596                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11597                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11598                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11599                 if (decalsystem->numdecals)
11600                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11601                 if (old.decals)
11602                         Mem_Free(old.decals);
11603                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11604                         decalsystem->element3i[i] = i;
11605                 if (useshortelements)
11606                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11607                                 decalsystem->element3s[i] = i;
11608         }
11609
11610         // grab a decal and search for another free slot for the next one
11611         decals = decalsystem->decals;
11612         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11613         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
11614                 ;
11615         decalsystem->freedecal = i;
11616         if (decalsystem->numdecals <= i)
11617                 decalsystem->numdecals = i + 1;
11618
11619         // initialize the decal
11620         decal->lived = 0;
11621         decal->triangleindex = triangleindex;
11622         decal->surfaceindex = surfaceindex;
11623         decal->decalsequence = decalsequence;
11624         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
11625         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
11626         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
11627         decal->color4ub[0][3] = 255;
11628         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
11629         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
11630         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
11631         decal->color4ub[1][3] = 255;
11632         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
11633         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
11634         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
11635         decal->color4ub[2][3] = 255;
11636         decal->vertex3f[0][0] = v0[0];
11637         decal->vertex3f[0][1] = v0[1];
11638         decal->vertex3f[0][2] = v0[2];
11639         decal->vertex3f[1][0] = v1[0];
11640         decal->vertex3f[1][1] = v1[1];
11641         decal->vertex3f[1][2] = v1[2];
11642         decal->vertex3f[2][0] = v2[0];
11643         decal->vertex3f[2][1] = v2[1];
11644         decal->vertex3f[2][2] = v2[2];
11645         decal->texcoord2f[0][0] = t0[0];
11646         decal->texcoord2f[0][1] = t0[1];
11647         decal->texcoord2f[1][0] = t1[0];
11648         decal->texcoord2f[1][1] = t1[1];
11649         decal->texcoord2f[2][0] = t2[0];
11650         decal->texcoord2f[2][1] = t2[1];
11651 }
11652
11653 extern cvar_t cl_decals_bias;
11654 extern cvar_t cl_decals_models;
11655 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11656 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)
11657 {
11658         matrix4x4_t projection;
11659         decalsystem_t *decalsystem;
11660         qboolean dynamic;
11661         dp_model_t *model;
11662         const float *vertex3f;
11663         const msurface_t *surface;
11664         const msurface_t *surfaces;
11665         const int *surfacelist;
11666         const texture_t *texture;
11667         int numtriangles;
11668         int numsurfacelist;
11669         int surfacelistindex;
11670         int surfaceindex;
11671         int triangleindex;
11672         int cornerindex;
11673         int index;
11674         int numpoints;
11675         const int *e;
11676         float localorigin[3];
11677         float localnormal[3];
11678         float localmins[3];
11679         float localmaxs[3];
11680         float localsize;
11681         float v[9][3];
11682         float tc[9][2];
11683         float c[9][4];
11684         //float normal[3];
11685         float planes[6][4];
11686         float f;
11687         float points[2][9][3];
11688         float angles[3];
11689         float temp[3];
11690
11691         decalsystem = &ent->decalsystem;
11692         model = ent->model;
11693         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11694         {
11695                 R_DecalSystem_Reset(&ent->decalsystem);
11696                 return;
11697         }
11698
11699         if (!model->brush.data_nodes && !cl_decals_models.integer)
11700         {
11701                 if (decalsystem->model)
11702                         R_DecalSystem_Reset(decalsystem);
11703                 return;
11704         }
11705
11706         if (decalsystem->model != model)
11707                 R_DecalSystem_Reset(decalsystem);
11708         decalsystem->model = model;
11709
11710         RSurf_ActiveModelEntity(ent, false, false, false);
11711
11712         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11713         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11714         VectorNormalize(localnormal);
11715         localsize = worldsize*rsurface.inversematrixscale;
11716         localmins[0] = localorigin[0] - localsize;
11717         localmins[1] = localorigin[1] - localsize;
11718         localmins[2] = localorigin[2] - localsize;
11719         localmaxs[0] = localorigin[0] + localsize;
11720         localmaxs[1] = localorigin[1] + localsize;
11721         localmaxs[2] = localorigin[2] + localsize;
11722
11723         //VectorCopy(localnormal, planes[4]);
11724         //VectorVectors(planes[4], planes[2], planes[0]);
11725         AnglesFromVectors(angles, localnormal, NULL, false);
11726         AngleVectors(angles, planes[0], planes[2], planes[4]);
11727         VectorNegate(planes[0], planes[1]);
11728         VectorNegate(planes[2], planes[3]);
11729         VectorNegate(planes[4], planes[5]);
11730         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11731         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11732         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11733         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11734         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11735         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11736
11737 #if 1
11738 // works
11739 {
11740         matrix4x4_t forwardprojection;
11741         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11742         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11743 }
11744 #else
11745 // broken
11746 {
11747         float projectionvector[4][3];
11748         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11749         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11750         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11751         projectionvector[0][0] = planes[0][0] * ilocalsize;
11752         projectionvector[0][1] = planes[1][0] * ilocalsize;
11753         projectionvector[0][2] = planes[2][0] * ilocalsize;
11754         projectionvector[1][0] = planes[0][1] * ilocalsize;
11755         projectionvector[1][1] = planes[1][1] * ilocalsize;
11756         projectionvector[1][2] = planes[2][1] * ilocalsize;
11757         projectionvector[2][0] = planes[0][2] * ilocalsize;
11758         projectionvector[2][1] = planes[1][2] * ilocalsize;
11759         projectionvector[2][2] = planes[2][2] * ilocalsize;
11760         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11761         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11762         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11763         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11764 }
11765 #endif
11766
11767         dynamic = model->surfmesh.isanimated;
11768         vertex3f = rsurface.modelvertex3f;
11769         numsurfacelist = model->nummodelsurfaces;
11770         surfacelist = model->sortedmodelsurfaces;
11771         surfaces = model->data_surfaces;
11772         for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11773         {
11774                 surfaceindex = surfacelist[surfacelistindex];
11775                 surface = surfaces + surfaceindex;
11776                 // check cull box first because it rejects more than any other check
11777                 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11778                         continue;
11779                 // skip transparent surfaces
11780                 texture = surface->texture;
11781                 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11782                         continue;
11783                 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11784                         continue;
11785                 numtriangles = surface->num_triangles;
11786                 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
11787                 {
11788                         for (cornerindex = 0;cornerindex < 3;cornerindex++)
11789                         {
11790                                 index = 3*e[cornerindex];
11791                                 VectorCopy(vertex3f + index, v[cornerindex]);
11792                         }
11793                         // cull backfaces
11794                         //TriangleNormal(v[0], v[1], v[2], normal);
11795                         //if (DotProduct(normal, localnormal) < 0.0f)
11796                         //      continue;
11797                         // clip by each of the box planes formed from the projection matrix
11798                         // if anything survives, we emit the decal
11799                         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]);
11800                         if (numpoints < 3)
11801                                 continue;
11802                         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]);
11803                         if (numpoints < 3)
11804                                 continue;
11805                         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]);
11806                         if (numpoints < 3)
11807                                 continue;
11808                         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]);
11809                         if (numpoints < 3)
11810                                 continue;
11811                         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]);
11812                         if (numpoints < 3)
11813                                 continue;
11814                         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]);
11815                         if (numpoints < 3)
11816                                 continue;
11817                         // some part of the triangle survived, so we have to accept it...
11818                         if (dynamic)
11819                         {
11820                                 // dynamic always uses the original triangle
11821                                 numpoints = 3;
11822                                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11823                                 {
11824                                         index = 3*e[cornerindex];
11825                                         VectorCopy(vertex3f + index, v[cornerindex]);
11826                                 }
11827                         }
11828                         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11829                         {
11830                                 // convert vertex positions to texcoords
11831                                 Matrix4x4_Transform(&projection, v[cornerindex], temp);
11832                                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11833                                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11834                                 // calculate distance fade from the projection origin
11835                                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11836                                 f = bound(0.0f, f, 1.0f);
11837                                 c[cornerindex][0] = r * f;
11838                                 c[cornerindex][1] = g * f;
11839                                 c[cornerindex][2] = b * f;
11840                                 c[cornerindex][3] = 1.0f;
11841                                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11842                         }
11843                         if (dynamic)
11844                                 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);
11845                         else
11846                                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11847                                         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);
11848                 }
11849         }
11850 }
11851
11852 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11853 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)
11854 {
11855         int renderentityindex;
11856         float worldmins[3];
11857         float worldmaxs[3];
11858         entity_render_t *ent;
11859
11860         if (!cl_decals_newsystem.integer)
11861                 return;
11862
11863         worldmins[0] = worldorigin[0] - worldsize;
11864         worldmins[1] = worldorigin[1] - worldsize;
11865         worldmins[2] = worldorigin[2] - worldsize;
11866         worldmaxs[0] = worldorigin[0] + worldsize;
11867         worldmaxs[1] = worldorigin[1] + worldsize;
11868         worldmaxs[2] = worldorigin[2] + worldsize;
11869
11870         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11871
11872         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11873         {
11874                 ent = r_refdef.scene.entities[renderentityindex];
11875                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11876                         continue;
11877
11878                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11879         }
11880 }
11881
11882 typedef struct r_decalsystem_splatqueue_s
11883 {
11884         vec3_t worldorigin;
11885         vec3_t worldnormal;
11886         float color[4];
11887         float tcrange[4];
11888         float worldsize;
11889         int decalsequence;
11890 }
11891 r_decalsystem_splatqueue_t;
11892
11893 int r_decalsystem_numqueued = 0;
11894 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11895
11896 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)
11897 {
11898         r_decalsystem_splatqueue_t *queue;
11899
11900         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11901                 return;
11902
11903         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11904         VectorCopy(worldorigin, queue->worldorigin);
11905         VectorCopy(worldnormal, queue->worldnormal);
11906         Vector4Set(queue->color, r, g, b, a);
11907         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11908         queue->worldsize = worldsize;
11909         queue->decalsequence = cl.decalsequence++;
11910 }
11911
11912 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11913 {
11914         int i;
11915         r_decalsystem_splatqueue_t *queue;
11916
11917         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11918                 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);
11919         r_decalsystem_numqueued = 0;
11920 }
11921
11922 extern cvar_t cl_decals_max;
11923 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11924 {
11925         int i;
11926         decalsystem_t *decalsystem = &ent->decalsystem;
11927         int numdecals;
11928         int killsequence;
11929         tridecal_t *decal;
11930         float frametime;
11931         float lifetime;
11932
11933         if (!decalsystem->numdecals)
11934                 return;
11935
11936         if (r_showsurfaces.integer)
11937                 return;
11938
11939         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11940         {
11941                 R_DecalSystem_Reset(decalsystem);
11942                 return;
11943         }
11944
11945         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11946         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11947
11948         if (decalsystem->lastupdatetime)
11949                 frametime = (cl.time - decalsystem->lastupdatetime);
11950         else
11951                 frametime = 0;
11952         decalsystem->lastupdatetime = cl.time;
11953         decal = decalsystem->decals;
11954         numdecals = decalsystem->numdecals;
11955
11956         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11957         {
11958                 if (decal->color4ub[0][3])
11959                 {
11960                         decal->lived += frametime;
11961                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11962                         {
11963                                 memset(decal, 0, sizeof(*decal));
11964                                 if (decalsystem->freedecal > i)
11965                                         decalsystem->freedecal = i;
11966                         }
11967                 }
11968         }
11969         decal = decalsystem->decals;
11970         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
11971                 numdecals--;
11972
11973         // collapse the array by shuffling the tail decals into the gaps
11974         for (;;)
11975         {
11976                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
11977                         decalsystem->freedecal++;
11978                 if (decalsystem->freedecal == numdecals)
11979                         break;
11980                 decal[decalsystem->freedecal] = decal[--numdecals];
11981         }
11982
11983         decalsystem->numdecals = numdecals;
11984
11985         if (numdecals <= 0)
11986         {
11987                 // if there are no decals left, reset decalsystem
11988                 R_DecalSystem_Reset(decalsystem);
11989         }
11990 }
11991
11992 extern skinframe_t *decalskinframe;
11993 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11994 {
11995         int i;
11996         decalsystem_t *decalsystem = &ent->decalsystem;
11997         int numdecals;
11998         tridecal_t *decal;
11999         float faderate;
12000         float alpha;
12001         float *v3f;
12002         float *c4f;
12003         float *t2f;
12004         const int *e;
12005         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12006         int numtris = 0;
12007
12008         numdecals = decalsystem->numdecals;
12009         if (!numdecals)
12010                 return;
12011
12012         if (r_showsurfaces.integer)
12013                 return;
12014
12015         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12016         {
12017                 R_DecalSystem_Reset(decalsystem);
12018                 return;
12019         }
12020
12021         // if the model is static it doesn't matter what value we give for
12022         // wantnormals and wanttangents, so this logic uses only rules applicable
12023         // to a model, knowing that they are meaningless otherwise
12024         if (ent == r_refdef.scene.worldentity)
12025                 RSurf_ActiveWorldEntity();
12026         else
12027                 RSurf_ActiveModelEntity(ent, false, false, false);
12028
12029         decalsystem->lastupdatetime = cl.time;
12030         decal = decalsystem->decals;
12031
12032         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12033
12034         // update vertex positions for animated models
12035         v3f = decalsystem->vertex3f;
12036         c4f = decalsystem->color4f;
12037         t2f = decalsystem->texcoord2f;
12038         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12039         {
12040                 if (!decal->color4ub[0][3])
12041                         continue;
12042
12043                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12044                         continue;
12045
12046                 // update color values for fading decals
12047                 if (decal->lived >= cl_decals_time.value)
12048                 {
12049                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12050                         alpha *= (1.0f/255.0f);
12051                 }
12052                 else
12053                         alpha = 1.0f/255.0f;
12054
12055                 c4f[ 0] = decal->color4ub[0][0] * alpha;
12056                 c4f[ 1] = decal->color4ub[0][1] * alpha;
12057                 c4f[ 2] = decal->color4ub[0][2] * alpha;
12058                 c4f[ 3] = 1;
12059                 c4f[ 4] = decal->color4ub[1][0] * alpha;
12060                 c4f[ 5] = decal->color4ub[1][1] * alpha;
12061                 c4f[ 6] = decal->color4ub[1][2] * alpha;
12062                 c4f[ 7] = 1;
12063                 c4f[ 8] = decal->color4ub[2][0] * alpha;
12064                 c4f[ 9] = decal->color4ub[2][1] * alpha;
12065                 c4f[10] = decal->color4ub[2][2] * alpha;
12066                 c4f[11] = 1;
12067
12068                 t2f[0] = decal->texcoord2f[0][0];
12069                 t2f[1] = decal->texcoord2f[0][1];
12070                 t2f[2] = decal->texcoord2f[1][0];
12071                 t2f[3] = decal->texcoord2f[1][1];
12072                 t2f[4] = decal->texcoord2f[2][0];
12073                 t2f[5] = decal->texcoord2f[2][1];
12074
12075                 // update vertex positions for animated models
12076                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
12077                 {
12078                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12079                         VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
12080                         VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
12081                         VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
12082                 }
12083                 else
12084                 {
12085                         VectorCopy(decal->vertex3f[0], v3f);
12086                         VectorCopy(decal->vertex3f[1], v3f + 3);
12087                         VectorCopy(decal->vertex3f[2], v3f + 6);
12088                 }
12089
12090                 if (r_refdef.fogenabled)
12091                 {
12092                         alpha = RSurf_FogVertex(v3f);
12093                         VectorScale(c4f, alpha, c4f);
12094                         alpha = RSurf_FogVertex(v3f + 3);
12095                         VectorScale(c4f + 4, alpha, c4f + 4);
12096                         alpha = RSurf_FogVertex(v3f + 6);
12097                         VectorScale(c4f + 8, alpha, c4f + 8);
12098                 }
12099
12100                 v3f += 9;
12101                 c4f += 12;
12102                 t2f += 6;
12103                 numtris++;
12104         }
12105
12106         if (numtris > 0)
12107         {
12108                 r_refdef.stats.drawndecals += numtris;
12109
12110                 // now render the decals all at once
12111                 // (this assumes they all use one particle font texture!)
12112                 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);
12113                 R_Mesh_ResetTextureState();
12114                 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
12115                 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
12116                 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
12117                 GL_DepthMask(false);
12118                 GL_DepthRange(0, 1);
12119                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12120                 GL_DepthTest(true);
12121                 GL_CullFace(GL_NONE);
12122                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12123                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
12124                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
12125         }
12126 }
12127
12128 static void R_DrawModelDecals(void)
12129 {
12130         int i, numdecals;
12131
12132         // fade faster when there are too many decals
12133         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12134         for (i = 0;i < r_refdef.scene.numentities;i++)
12135                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12136
12137         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12138         for (i = 0;i < r_refdef.scene.numentities;i++)
12139                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12140                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12141
12142         R_DecalSystem_ApplySplatEntitiesQueue();
12143
12144         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12145         for (i = 0;i < r_refdef.scene.numentities;i++)
12146                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12147
12148         r_refdef.stats.totaldecals += numdecals;
12149
12150         if (r_showsurfaces.integer)
12151                 return;
12152
12153         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12154
12155         for (i = 0;i < r_refdef.scene.numentities;i++)
12156         {
12157                 if (!r_refdef.viewcache.entityvisible[i])
12158                         continue;
12159                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12160                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12161         }
12162 }
12163
12164 extern cvar_t mod_collision_bih;
12165 void R_DrawDebugModel(void)
12166 {
12167         entity_render_t *ent = rsurface.entity;
12168         int i, j, k, l, flagsmask;
12169         const msurface_t *surface;
12170         dp_model_t *model = ent->model;
12171         vec3_t v;
12172
12173         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12174
12175         R_Mesh_ColorPointer(NULL, 0, 0);
12176         R_Mesh_ResetTextureState();
12177         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12178         GL_DepthRange(0, 1);
12179         GL_DepthTest(!r_showdisabledepthtest.integer);
12180         GL_DepthMask(false);
12181         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12182
12183         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12184         {
12185                 int triangleindex;
12186                 int bihleafindex;
12187                 qboolean cullbox = ent == r_refdef.scene.worldentity;
12188                 const q3mbrush_t *brush;
12189                 const bih_t *bih = &model->collision_bih;
12190                 const bih_leaf_t *bihleaf;
12191                 float vertex3f[3][3];
12192                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12193                 cullbox = false;
12194                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12195                 {
12196                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12197                                 continue;
12198                         switch (bihleaf->type)
12199                         {
12200                         case BIH_BRUSH:
12201                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12202                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12203                                 {
12204                                         R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
12205                                         GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
12206                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
12207                                 }
12208                                 break;
12209                         case BIH_COLLISIONTRIANGLE:
12210                                 triangleindex = bihleaf->itemindex;
12211                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12212                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12213                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12214                                 R_Mesh_VertexPointer(vertex3f[0], 0, 0);
12215                                 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
12216                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, polygonelement3s, 0, 0);
12217                                 break;
12218                         case BIH_RENDERTRIANGLE:
12219                                 triangleindex = bihleaf->itemindex;
12220                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12221                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12222                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12223                                 R_Mesh_VertexPointer(vertex3f[0], 0, 0);
12224                                 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
12225                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, polygonelement3s, 0, 0);
12226                                 break;
12227                         }
12228                 }
12229         }
12230
12231         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12232
12233         if (r_showtris.integer || r_shownormals.integer)
12234         {
12235                 if (r_showdisabledepthtest.integer)
12236                 {
12237                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12238                         GL_DepthMask(false);
12239                 }
12240                 else
12241                 {
12242                         GL_BlendFunc(GL_ONE, GL_ZERO);
12243                         GL_DepthMask(true);
12244                 }
12245                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12246                 {
12247                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12248                                 continue;
12249                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12250                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12251                         {
12252                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
12253                                 if (r_showtris.value > 0)
12254                                 {
12255                                         if (!rsurface.texture->currentlayers->depthmask)
12256                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12257                                         else if (ent == r_refdef.scene.worldentity)
12258                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12259                                         else
12260                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12261                                         R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
12262                                         R_Mesh_ColorPointer(NULL, 0, 0);
12263                                         R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
12264                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
12265                                         //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
12266                                         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);
12267                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
12268                                         CHECKGLERROR
12269                                 }
12270                                 if (r_shownormals.value < 0)
12271                                 {
12272                                         qglBegin(GL_LINES);
12273                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12274                                         {
12275                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
12276                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12277                                                 qglVertex3f(v[0], v[1], v[2]);
12278                                                 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
12279                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12280                                                 qglVertex3f(v[0], v[1], v[2]);
12281                                         }
12282                                         qglEnd();
12283                                         CHECKGLERROR
12284                                 }
12285                                 if (r_shownormals.value > 0)
12286                                 {
12287                                         qglBegin(GL_LINES);
12288                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12289                                         {
12290                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
12291                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12292                                                 qglVertex3f(v[0], v[1], v[2]);
12293                                                 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
12294                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12295                                                 qglVertex3f(v[0], v[1], v[2]);
12296                                         }
12297                                         qglEnd();
12298                                         CHECKGLERROR
12299                                         qglBegin(GL_LINES);
12300                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12301                                         {
12302                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
12303                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12304                                                 qglVertex3f(v[0], v[1], v[2]);
12305                                                 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
12306                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12307                                                 qglVertex3f(v[0], v[1], v[2]);
12308                                         }
12309                                         qglEnd();
12310                                         CHECKGLERROR
12311                                         qglBegin(GL_LINES);
12312                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12313                                         {
12314                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
12315                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12316                                                 qglVertex3f(v[0], v[1], v[2]);
12317                                                 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
12318                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12319                                                 qglVertex3f(v[0], v[1], v[2]);
12320                                         }
12321                                         qglEnd();
12322                                         CHECKGLERROR
12323                                 }
12324                         }
12325                 }
12326                 rsurface.texture = NULL;
12327         }
12328 }
12329
12330 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
12331 int r_maxsurfacelist = 0;
12332 const msurface_t **r_surfacelist = NULL;
12333 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12334 {
12335         int i, j, endj, flagsmask;
12336         dp_model_t *model = r_refdef.scene.worldmodel;
12337         msurface_t *surfaces;
12338         unsigned char *update;
12339         int numsurfacelist = 0;
12340         if (model == NULL)
12341                 return;
12342
12343         if (r_maxsurfacelist < model->num_surfaces)
12344         {
12345                 r_maxsurfacelist = model->num_surfaces;
12346                 if (r_surfacelist)
12347                         Mem_Free((msurface_t**)r_surfacelist);
12348                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12349         }
12350
12351         RSurf_ActiveWorldEntity();
12352
12353         surfaces = model->data_surfaces;
12354         update = model->brushq1.lightmapupdateflags;
12355
12356         // update light styles on this submodel
12357         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12358         {
12359                 model_brush_lightstyleinfo_t *style;
12360                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12361                 {
12362                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12363                         {
12364                                 int *list = style->surfacelist;
12365                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12366                                 for (j = 0;j < style->numsurfaces;j++)
12367                                         update[list[j]] = true;
12368                         }
12369                 }
12370         }
12371
12372         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12373
12374         if (debug)
12375         {
12376                 R_DrawDebugModel();
12377                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12378                 return;
12379         }
12380
12381         rsurface.uselightmaptexture = false;
12382         rsurface.texture = NULL;
12383         rsurface.rtlight = NULL;
12384         numsurfacelist = 0;
12385         // add visible surfaces to draw list
12386         for (i = 0;i < model->nummodelsurfaces;i++)
12387         {
12388                 j = model->sortedmodelsurfaces[i];
12389                 if (r_refdef.viewcache.world_surfacevisible[j])
12390                         r_surfacelist[numsurfacelist++] = surfaces + j;
12391         }
12392         // update lightmaps if needed
12393         if (model->brushq1.firstrender)
12394         {
12395                 model->brushq1.firstrender = false;
12396                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12397                         if (update[j])
12398                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12399         }
12400         else if (update)
12401         {
12402                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12403                         if (r_refdef.viewcache.world_surfacevisible[j])
12404                                 if (update[j])
12405                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12406         }
12407         // don't do anything if there were no surfaces
12408         if (!numsurfacelist)
12409         {
12410                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12411                 return;
12412         }
12413         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12414         GL_AlphaTest(false);
12415
12416         // add to stats if desired
12417         if (r_speeds.integer && !skysurfaces && !depthonly)
12418         {
12419                 r_refdef.stats.world_surfaces += numsurfacelist;
12420                 for (j = 0;j < numsurfacelist;j++)
12421                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
12422         }
12423
12424         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12425 }
12426
12427 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12428 {
12429         int i, j, endj, flagsmask;
12430         dp_model_t *model = ent->model;
12431         msurface_t *surfaces;
12432         unsigned char *update;
12433         int numsurfacelist = 0;
12434         if (model == NULL)
12435                 return;
12436
12437         if (r_maxsurfacelist < model->num_surfaces)
12438         {
12439                 r_maxsurfacelist = model->num_surfaces;
12440                 if (r_surfacelist)
12441                         Mem_Free((msurface_t **)r_surfacelist);
12442                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12443         }
12444
12445         // if the model is static it doesn't matter what value we give for
12446         // wantnormals and wanttangents, so this logic uses only rules applicable
12447         // to a model, knowing that they are meaningless otherwise
12448         if (ent == r_refdef.scene.worldentity)
12449                 RSurf_ActiveWorldEntity();
12450         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12451                 RSurf_ActiveModelEntity(ent, false, false, false);
12452         else if (prepass)
12453                 RSurf_ActiveModelEntity(ent, true, true, true);
12454         else if (depthonly)
12455         {
12456                 switch (vid.renderpath)
12457                 {
12458                 case RENDERPATH_GL20:
12459                 case RENDERPATH_CGGL:
12460                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12461                         break;
12462                 case RENDERPATH_GL13:
12463                 case RENDERPATH_GL11:
12464                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12465                         break;
12466                 }
12467         }
12468         else
12469         {
12470                 switch (vid.renderpath)
12471                 {
12472                 case RENDERPATH_GL20:
12473                 case RENDERPATH_CGGL:
12474                         RSurf_ActiveModelEntity(ent, true, true, false);
12475                         break;
12476                 case RENDERPATH_GL13:
12477                 case RENDERPATH_GL11:
12478                         RSurf_ActiveModelEntity(ent, true, false, false);
12479                         break;
12480                 }
12481         }
12482
12483         surfaces = model->data_surfaces;
12484         update = model->brushq1.lightmapupdateflags;
12485
12486         // update light styles
12487         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12488         {
12489                 model_brush_lightstyleinfo_t *style;
12490                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12491                 {
12492                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12493                         {
12494                                 int *list = style->surfacelist;
12495                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12496                                 for (j = 0;j < style->numsurfaces;j++)
12497                                         update[list[j]] = true;
12498                         }
12499                 }
12500         }
12501
12502         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12503
12504         if (debug)
12505         {
12506                 R_DrawDebugModel();
12507                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12508                 return;
12509         }
12510
12511         rsurface.uselightmaptexture = false;
12512         rsurface.texture = NULL;
12513         rsurface.rtlight = NULL;
12514         numsurfacelist = 0;
12515         // add visible surfaces to draw list
12516         for (i = 0;i < model->nummodelsurfaces;i++)
12517                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12518         // don't do anything if there were no surfaces
12519         if (!numsurfacelist)
12520         {
12521                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12522                 return;
12523         }
12524         // update lightmaps if needed
12525         if (update)
12526         {
12527                 int updated = 0;
12528                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12529                 {
12530                         if (update[j])
12531                         {
12532                                 updated++;
12533                                 R_BuildLightMap(ent, surfaces + j);
12534                         }
12535                 }
12536         }
12537         if (update)
12538                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12539                         if (update[j])
12540                                 R_BuildLightMap(ent, surfaces + j);
12541         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12542         GL_AlphaTest(false);
12543
12544         // add to stats if desired
12545         if (r_speeds.integer && !skysurfaces && !depthonly)
12546         {
12547                 r_refdef.stats.entities_surfaces += numsurfacelist;
12548                 for (j = 0;j < numsurfacelist;j++)
12549                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
12550         }
12551
12552         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12553 }
12554
12555 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12556 {
12557         static texture_t texture;
12558         static msurface_t surface;
12559         const msurface_t *surfacelist = &surface;
12560
12561         // fake enough texture and surface state to render this geometry
12562
12563         texture.update_lastrenderframe = -1; // regenerate this texture
12564         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12565         texture.currentskinframe = skinframe;
12566         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12567         texture.offsetmapping = OFFSETMAPPING_OFF;
12568         texture.offsetscale = 1;
12569         texture.specularscalemod = 1;
12570         texture.specularpowermod = 1;
12571
12572         surface.texture = &texture;
12573         surface.num_triangles = numtriangles;
12574         surface.num_firsttriangle = firsttriangle;
12575         surface.num_vertices = numvertices;
12576         surface.num_firstvertex = firstvertex;
12577
12578         // now render it
12579         rsurface.texture = R_GetCurrentTexture(surface.texture);
12580         rsurface.uselightmaptexture = false;
12581         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12582 }
12583
12584 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)
12585 {
12586         static msurface_t surface;
12587         const msurface_t *surfacelist = &surface;
12588
12589         // fake enough texture and surface state to render this geometry
12590
12591         surface.texture = texture;
12592         surface.num_triangles = numtriangles;
12593         surface.num_firsttriangle = firsttriangle;
12594         surface.num_vertices = numvertices;
12595         surface.num_firstvertex = firstvertex;
12596
12597         // now render it
12598         rsurface.texture = R_GetCurrentTexture(surface.texture);
12599         rsurface.uselightmaptexture = false;
12600         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12601 }