]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
change texcoord assignments in Cg shader back to the way it was, because
[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 #include "csprogs.h"
29
30 mempool_t *r_main_mempool;
31 rtexturepool_t *r_main_texturepool;
32
33 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
34
35 static qboolean r_loadnormalmap;
36 static qboolean r_loadgloss;
37 qboolean r_loadfog;
38 static qboolean r_loaddds;
39 static qboolean r_savedds;
40
41 //
42 // screen size info
43 //
44 r_refdef_t r_refdef;
45
46 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
47 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
48 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
49 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
50 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)"};
51 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
52 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
53 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
54
55 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
56 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"};
57 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
58 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)"};
59 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
60
61 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"};
62 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
63 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
64 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
65 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
66 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
67 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)"};
68 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
69 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
70 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"};
71 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"};
72 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
73 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"};
74 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"};
75 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"};
76 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
77 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
78 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
79 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
80 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
81 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)"};
82 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)"};
83 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
84 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
85 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
86 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
87 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
88 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
89 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
90 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."};
91 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
92 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
93 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
94 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."};
95 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
96 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
97 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
98 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
99 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"};
100 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"};
101 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
102 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
103 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
104 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
105 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"};
106
107 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
108 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
109 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
110 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
111 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
112 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
113 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
114 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
115
116 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)"};
117 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"};
118
119 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
120 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
121 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
122 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
123 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
124
125 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
126 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
127 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
128
129 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)"};
130 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
131 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
132 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
133 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
134 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)"};
135 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)"};
136 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)"};
137 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)"};
138
139 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)"};
140 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
141 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"};
142 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
143 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
144
145 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
146 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
147 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
148 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
149
150 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
151 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
152 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
153 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
154 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
155 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
156 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
157
158 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
159 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
160 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
161 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)"};
162
163 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"};
164
165 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"};
166
167 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
168
169 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
170 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
171 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"};
172 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
173 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
174 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
175 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
176 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)"};
177
178 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
179
180 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)"};
181
182 extern cvar_t v_glslgamma;
183
184 extern qboolean v_flipped_state;
185
186 static struct r_bloomstate_s
187 {
188         qboolean enabled;
189         qboolean hdr;
190
191         int bloomwidth, bloomheight;
192
193         int screentexturewidth, screentextureheight;
194         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
195
196         int bloomtexturewidth, bloomtextureheight;
197         rtexture_t *texture_bloom;
198
199         // arrays for rendering the screen passes
200         float screentexcoord2f[8];
201         float bloomtexcoord2f[8];
202         float offsettexcoord2f[8];
203
204         r_viewport_t viewport;
205 }
206 r_bloomstate;
207
208 r_waterstate_t r_waterstate;
209
210 /// shadow volume bsp struct with automatically growing nodes buffer
211 svbsp_t r_svbsp;
212
213 rtexture_t *r_texture_blanknormalmap;
214 rtexture_t *r_texture_white;
215 rtexture_t *r_texture_grey128;
216 rtexture_t *r_texture_black;
217 rtexture_t *r_texture_notexture;
218 rtexture_t *r_texture_whitecube;
219 rtexture_t *r_texture_normalizationcube;
220 rtexture_t *r_texture_fogattenuation;
221 rtexture_t *r_texture_fogheighttexture;
222 rtexture_t *r_texture_gammaramps;
223 unsigned int r_texture_gammaramps_serial;
224 //rtexture_t *r_texture_fogintensity;
225 rtexture_t *r_texture_reflectcube;
226
227 // TODO: hash lookups?
228 typedef struct cubemapinfo_s
229 {
230         char basename[64];
231         rtexture_t *texture;
232 }
233 cubemapinfo_t;
234
235 int r_texture_numcubemaps;
236 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
237
238 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
239 unsigned int r_numqueries;
240 unsigned int r_maxqueries;
241
242 typedef struct r_qwskincache_s
243 {
244         char name[MAX_QPATH];
245         skinframe_t *skinframe;
246 }
247 r_qwskincache_t;
248
249 static r_qwskincache_t *r_qwskincache;
250 static int r_qwskincache_size;
251
252 /// vertex coordinates for a quad that covers the screen exactly
253 const float r_screenvertex3f[12] =
254 {
255         0, 0, 0,
256         1, 0, 0,
257         1, 1, 0,
258         0, 1, 0
259 };
260
261 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
262 {
263         int i;
264         for (i = 0;i < verts;i++)
265         {
266                 out[0] = in[0] * r;
267                 out[1] = in[1] * g;
268                 out[2] = in[2] * b;
269                 out[3] = in[3];
270                 in += 4;
271                 out += 4;
272         }
273 }
274
275 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
276 {
277         int i;
278         for (i = 0;i < verts;i++)
279         {
280                 out[0] = r;
281                 out[1] = g;
282                 out[2] = b;
283                 out[3] = a;
284                 out += 4;
285         }
286 }
287
288 // FIXME: move this to client?
289 void FOG_clear(void)
290 {
291         if (gamemode == GAME_NEHAHRA)
292         {
293                 Cvar_Set("gl_fogenable", "0");
294                 Cvar_Set("gl_fogdensity", "0.2");
295                 Cvar_Set("gl_fogred", "0.3");
296                 Cvar_Set("gl_foggreen", "0.3");
297                 Cvar_Set("gl_fogblue", "0.3");
298         }
299         r_refdef.fog_density = 0;
300         r_refdef.fog_red = 0;
301         r_refdef.fog_green = 0;
302         r_refdef.fog_blue = 0;
303         r_refdef.fog_alpha = 1;
304         r_refdef.fog_start = 0;
305         r_refdef.fog_end = 16384;
306         r_refdef.fog_height = 1<<30;
307         r_refdef.fog_fadedepth = 128;
308         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
309 }
310
311 static void R_BuildBlankTextures(void)
312 {
313         unsigned char data[4];
314         data[2] = 128; // normal X
315         data[1] = 128; // normal Y
316         data[0] = 255; // normal Z
317         data[3] = 128; // height
318         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
319         data[0] = 255;
320         data[1] = 255;
321         data[2] = 255;
322         data[3] = 255;
323         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
324         data[0] = 128;
325         data[1] = 128;
326         data[2] = 128;
327         data[3] = 255;
328         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
329         data[0] = 0;
330         data[1] = 0;
331         data[2] = 0;
332         data[3] = 255;
333         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
334 }
335
336 static void R_BuildNoTexture(void)
337 {
338         int x, y;
339         unsigned char pix[16][16][4];
340         // this makes a light grey/dark grey checkerboard texture
341         for (y = 0;y < 16;y++)
342         {
343                 for (x = 0;x < 16;x++)
344                 {
345                         if ((y < 8) ^ (x < 8))
346                         {
347                                 pix[y][x][0] = 128;
348                                 pix[y][x][1] = 128;
349                                 pix[y][x][2] = 128;
350                                 pix[y][x][3] = 255;
351                         }
352                         else
353                         {
354                                 pix[y][x][0] = 64;
355                                 pix[y][x][1] = 64;
356                                 pix[y][x][2] = 64;
357                                 pix[y][x][3] = 255;
358                         }
359                 }
360         }
361         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
362 }
363
364 static void R_BuildWhiteCube(void)
365 {
366         unsigned char data[6*1*1*4];
367         memset(data, 255, sizeof(data));
368         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
369 }
370
371 static void R_BuildNormalizationCube(void)
372 {
373         int x, y, side;
374         vec3_t v;
375         vec_t s, t, intensity;
376 #define NORMSIZE 64
377         unsigned char *data;
378         data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
379         for (side = 0;side < 6;side++)
380         {
381                 for (y = 0;y < NORMSIZE;y++)
382                 {
383                         for (x = 0;x < NORMSIZE;x++)
384                         {
385                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
386                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
387                                 switch(side)
388                                 {
389                                 default:
390                                 case 0:
391                                         v[0] = 1;
392                                         v[1] = -t;
393                                         v[2] = -s;
394                                         break;
395                                 case 1:
396                                         v[0] = -1;
397                                         v[1] = -t;
398                                         v[2] = s;
399                                         break;
400                                 case 2:
401                                         v[0] = s;
402                                         v[1] = 1;
403                                         v[2] = t;
404                                         break;
405                                 case 3:
406                                         v[0] = s;
407                                         v[1] = -1;
408                                         v[2] = -t;
409                                         break;
410                                 case 4:
411                                         v[0] = s;
412                                         v[1] = -t;
413                                         v[2] = 1;
414                                         break;
415                                 case 5:
416                                         v[0] = -s;
417                                         v[1] = -t;
418                                         v[2] = -1;
419                                         break;
420                                 }
421                                 intensity = 127.0f / sqrt(DotProduct(v, v));
422                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
423                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
424                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
425                                 data[((side*64+y)*64+x)*4+3] = 255;
426                         }
427                 }
428         }
429         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
430         Mem_Free(data);
431 }
432
433 static void R_BuildFogTexture(void)
434 {
435         int x, b;
436 #define FOGWIDTH 256
437         unsigned char data1[FOGWIDTH][4];
438         //unsigned char data2[FOGWIDTH][4];
439         double d, r, alpha;
440
441         r_refdef.fogmasktable_start = r_refdef.fog_start;
442         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
443         r_refdef.fogmasktable_range = r_refdef.fogrange;
444         r_refdef.fogmasktable_density = r_refdef.fog_density;
445
446         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
447         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
448         {
449                 d = (x * r - r_refdef.fogmasktable_start);
450                 if(developer_extra.integer)
451                         Con_DPrintf("%f ", d);
452                 d = max(0, d);
453                 if (r_fog_exp2.integer)
454                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
455                 else
456                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
457                 if(developer_extra.integer)
458                         Con_DPrintf(" : %f ", alpha);
459                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
460                 if(developer_extra.integer)
461                         Con_DPrintf(" = %f\n", alpha);
462                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
463         }
464
465         for (x = 0;x < FOGWIDTH;x++)
466         {
467                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
468                 data1[x][0] = b;
469                 data1[x][1] = b;
470                 data1[x][2] = b;
471                 data1[x][3] = 255;
472                 //data2[x][0] = 255 - b;
473                 //data2[x][1] = 255 - b;
474                 //data2[x][2] = 255 - b;
475                 //data2[x][3] = 255;
476         }
477         if (r_texture_fogattenuation)
478         {
479                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
480                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
481         }
482         else
483         {
484                 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);
485                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
486         }
487 }
488
489 static void R_BuildFogHeightTexture(void)
490 {
491         unsigned char *inpixels;
492         int size;
493         int x;
494         int y;
495         int j;
496         float c[4];
497         float f;
498         inpixels = NULL;
499         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
500         if (r_refdef.fogheighttexturename[0])
501                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false);
502         if (!inpixels)
503         {
504                 r_refdef.fog_height_tablesize = 0;
505                 if (r_texture_fogheighttexture)
506                         R_FreeTexture(r_texture_fogheighttexture);
507                 r_texture_fogheighttexture = NULL;
508                 if (r_refdef.fog_height_table2d)
509                         Mem_Free(r_refdef.fog_height_table2d);
510                 r_refdef.fog_height_table2d = NULL;
511                 if (r_refdef.fog_height_table1d)
512                         Mem_Free(r_refdef.fog_height_table1d);
513                 r_refdef.fog_height_table1d = NULL;
514                 return;
515         }
516         size = image_width;
517         r_refdef.fog_height_tablesize = size;
518         r_refdef.fog_height_table1d = Mem_Alloc(r_main_mempool, size * 4);
519         r_refdef.fog_height_table2d = Mem_Alloc(r_main_mempool, size * size * 4);
520         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
521         Mem_Free(inpixels);
522         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
523         // average fog color table accounting for every fog layer between a point
524         // and the camera.  (Note: attenuation is handled separately!)
525         for (y = 0;y < size;y++)
526         {
527                 for (x = 0;x < size;x++)
528                 {
529                         Vector4Clear(c);
530                         f = 0;
531                         if (x < y)
532                         {
533                                 for (j = x;j <= y;j++)
534                                 {
535                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
536                                         f++;
537                                 }
538                         }
539                         else
540                         {
541                                 for (j = x;j >= y;j--)
542                                 {
543                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
544                                         f++;
545                                 }
546                         }
547                         f = 1.0f / f;
548                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
549                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
550                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
551                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
552                 }
553         }
554         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, NULL);
555 }
556
557 //=======================================================================================================================================================
558
559 static const char *builtinshaderstring =
560 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
561 "// written by Forest 'LordHavoc' Hale\n"
562 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
563 "\n"
564 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
565 "# define USEFOG\n"
566 "#endif\n"
567 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
568 "#define USELIGHTMAP\n"
569 "#endif\n"
570 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
571 "#define USEEYEVECTOR\n"
572 "#endif\n"
573 "\n"
574 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
575 "# extension GL_ARB_texture_rectangle : enable\n"
576 "#endif\n"
577 "\n"
578 "#ifdef USESHADOWMAP2D\n"
579 "# ifdef GL_EXT_gpu_shader4\n"
580 "#   extension GL_EXT_gpu_shader4 : enable\n"
581 "# endif\n"
582 "# ifdef GL_ARB_texture_gather\n"
583 "#   extension GL_ARB_texture_gather : enable\n"
584 "# else\n"
585 "#   ifdef GL_AMD_texture_texture4\n"
586 "#     extension GL_AMD_texture_texture4 : enable\n"
587 "#   endif\n"
588 "# endif\n"
589 "#endif\n"
590 "\n"
591 "#ifdef USESHADOWMAPCUBE\n"
592 "# extension GL_EXT_gpu_shader4 : enable\n"
593 "#endif\n"
594 "\n"
595 "//#ifdef USESHADOWSAMPLER\n"
596 "//# extension GL_ARB_shadow : enable\n"
597 "//#endif\n"
598 "\n"
599 "//#ifdef __GLSL_CG_DATA_TYPES\n"
600 "//# define myhalf half\n"
601 "//# define myhalf2 half2\n"
602 "//# define myhalf3 half3\n"
603 "//# define myhalf4 half4\n"
604 "//#else\n"
605 "# define myhalf float\n"
606 "# define myhalf2 vec2\n"
607 "# define myhalf3 vec3\n"
608 "# define myhalf4 vec4\n"
609 "//#endif\n"
610 "\n"
611 "#ifdef VERTEX_SHADER\n"
612 "uniform mat4 ModelViewProjectionMatrix;\n"
613 "#endif\n"
614 "\n"
615 "#ifdef MODE_DEPTH_OR_SHADOW\n"
616 "#ifdef VERTEX_SHADER\n"
617 "void main(void)\n"
618 "{\n"
619 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
620 "}\n"
621 "#endif\n"
622 "#else // !MODE_DEPTH_ORSHADOW\n"
623 "\n"
624 "\n"
625 "\n"
626 "\n"
627 "#ifdef MODE_SHOWDEPTH\n"
628 "#ifdef VERTEX_SHADER\n"
629 "void main(void)\n"
630 "{\n"
631 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
632 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
633 "}\n"
634 "#endif\n"
635 "\n"
636 "#ifdef FRAGMENT_SHADER\n"
637 "void main(void)\n"
638 "{\n"
639 "       gl_FragColor = gl_Color;\n"
640 "}\n"
641 "#endif\n"
642 "#else // !MODE_SHOWDEPTH\n"
643 "\n"
644 "\n"
645 "\n"
646 "\n"
647 "#ifdef MODE_POSTPROCESS\n"
648 "varying vec2 TexCoord1;\n"
649 "varying vec2 TexCoord2;\n"
650 "\n"
651 "#ifdef VERTEX_SHADER\n"
652 "void main(void)\n"
653 "{\n"
654 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
655 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
656 "#ifdef USEBLOOM\n"
657 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
658 "#endif\n"
659 "}\n"
660 "#endif\n"
661 "\n"
662 "#ifdef FRAGMENT_SHADER\n"
663 "uniform sampler2D Texture_First;\n"
664 "#ifdef USEBLOOM\n"
665 "uniform sampler2D Texture_Second;\n"
666 "#endif\n"
667 "#ifdef USEGAMMARAMPS\n"
668 "uniform sampler2D Texture_GammaRamps;\n"
669 "#endif\n"
670 "#ifdef USESATURATION\n"
671 "uniform float Saturation;\n"
672 "#endif\n"
673 "#ifdef USEVIEWTINT\n"
674 "uniform vec4 ViewTintColor;\n"
675 "#endif\n"
676 "//uncomment these if you want to use them:\n"
677 "uniform vec4 UserVec1;\n"
678 "// uniform vec4 UserVec2;\n"
679 "// uniform vec4 UserVec3;\n"
680 "// uniform vec4 UserVec4;\n"
681 "// uniform float ClientTime;\n"
682 "uniform vec2 PixelSize;\n"
683 "void main(void)\n"
684 "{\n"
685 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
686 "#ifdef USEBLOOM\n"
687 "       gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
688 "#endif\n"
689 "#ifdef USEVIEWTINT\n"
690 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
691 "#endif\n"
692 "\n"
693 "#ifdef USEPOSTPROCESSING\n"
694 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
695 "// 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"
696 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
697 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
698 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
699 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
700 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
701 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
702 "#endif\n"
703 "\n"
704 "#ifdef USESATURATION\n"
705 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
706 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
707 "       //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
708 "       gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
709 "#endif\n"
710 "\n"
711 "#ifdef USEGAMMARAMPS\n"
712 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
713 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
714 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
715 "#endif\n"
716 "}\n"
717 "#endif\n"
718 "#else // !MODE_POSTPROCESS\n"
719 "\n"
720 "\n"
721 "\n"
722 "\n"
723 "#ifdef MODE_GENERIC\n"
724 "#ifdef USEDIFFUSE\n"
725 "varying vec2 TexCoord1;\n"
726 "#endif\n"
727 "#ifdef USESPECULAR\n"
728 "varying vec2 TexCoord2;\n"
729 "#endif\n"
730 "#ifdef VERTEX_SHADER\n"
731 "void main(void)\n"
732 "{\n"
733 "       gl_FrontColor = gl_Color;\n"
734 "#ifdef USEDIFFUSE\n"
735 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
736 "#endif\n"
737 "#ifdef USESPECULAR\n"
738 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
739 "#endif\n"
740 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
741 "}\n"
742 "#endif\n"
743 "\n"
744 "#ifdef FRAGMENT_SHADER\n"
745 "#ifdef USEDIFFUSE\n"
746 "uniform sampler2D Texture_First;\n"
747 "#endif\n"
748 "#ifdef USESPECULAR\n"
749 "uniform sampler2D Texture_Second;\n"
750 "#endif\n"
751 "\n"
752 "void main(void)\n"
753 "{\n"
754 "       gl_FragColor = gl_Color;\n"
755 "#ifdef USEDIFFUSE\n"
756 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
757 "#endif\n"
758 "\n"
759 "#ifdef USESPECULAR\n"
760 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
761 "# ifdef USECOLORMAPPING\n"
762 "       gl_FragColor *= tex2;\n"
763 "# endif\n"
764 "# ifdef USEGLOW\n"
765 "       gl_FragColor += tex2;\n"
766 "# endif\n"
767 "# ifdef USEVERTEXTEXTUREBLEND\n"
768 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
769 "# endif\n"
770 "#endif\n"
771 "}\n"
772 "#endif\n"
773 "#else // !MODE_GENERIC\n"
774 "\n"
775 "\n"
776 "\n"
777 "\n"
778 "#ifdef MODE_BLOOMBLUR\n"
779 "varying TexCoord;\n"
780 "#ifdef VERTEX_SHADER\n"
781 "void main(void)\n"
782 "{\n"
783 "       gl_FrontColor = gl_Color;\n"
784 "       TexCoord = gl_MultiTexCoord0.xy;\n"
785 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
786 "}\n"
787 "#endif\n"
788 "\n"
789 "#ifdef FRAGMENT_SHADER\n"
790 "uniform sampler2D Texture_First;\n"
791 "uniform vec4 BloomBlur_Parameters;\n"
792 "\n"
793 "void main(void)\n"
794 "{\n"
795 "       int i;\n"
796 "       vec2 tc = TexCoord;\n"
797 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
798 "       tc += BloomBlur_Parameters.xy;\n"
799 "       for (i = 1;i < SAMPLES;i++)\n"
800 "       {\n"
801 "               color += texture2D(Texture_First, tc).rgb;\n"
802 "               tc += BloomBlur_Parameters.xy;\n"
803 "       }\n"
804 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
805 "}\n"
806 "#endif\n"
807 "#else // !MODE_BLOOMBLUR\n"
808 "#ifdef MODE_REFRACTION\n"
809 "varying vec2 TexCoord;\n"
810 "varying vec4 ModelViewProjectionPosition;\n"
811 "uniform mat4 TexMatrix;\n"
812 "#ifdef VERTEX_SHADER\n"
813 "\n"
814 "void main(void)\n"
815 "{\n"
816 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
817 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
818 "       ModelViewProjectionPosition = gl_Position;\n"
819 "}\n"
820 "#endif\n"
821 "\n"
822 "#ifdef FRAGMENT_SHADER\n"
823 "uniform sampler2D Texture_Normal;\n"
824 "uniform sampler2D Texture_Refraction;\n"
825 "uniform sampler2D Texture_Reflection;\n"
826 "\n"
827 "uniform vec4 DistortScaleRefractReflect;\n"
828 "uniform vec4 ScreenScaleRefractReflect;\n"
829 "uniform vec4 ScreenCenterRefractReflect;\n"
830 "uniform vec4 RefractColor;\n"
831 "uniform vec4 ReflectColor;\n"
832 "uniform float ReflectFactor;\n"
833 "uniform float ReflectOffset;\n"
834 "\n"
835 "void main(void)\n"
836 "{\n"
837 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
838 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
839 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
840 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
841 "       // FIXME temporary hack to detect the case that the reflection\n"
842 "       // gets blackened at edges due to leaving the area that contains actual\n"
843 "       // content.\n"
844 "       // Remove this 'ack once we have a better way to stop this thing from\n"
845 "       // 'appening.\n"
846 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
847 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
848 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
849 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
850 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
851 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
852 "}\n"
853 "#endif\n"
854 "#else // !MODE_REFRACTION\n"
855 "\n"
856 "\n"
857 "\n"
858 "\n"
859 "#ifdef MODE_WATER\n"
860 "varying vec2 TexCoord;\n"
861 "varying vec3 EyeVector;\n"
862 "varying vec4 ModelViewProjectionPosition;\n"
863 "#ifdef VERTEX_SHADER\n"
864 "uniform vec3 EyePosition;\n"
865 "uniform mat4 TexMatrix;\n"
866 "\n"
867 "void main(void)\n"
868 "{\n"
869 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
870 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
871 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
872 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
873 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
874 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
875 "       ModelViewProjectionPosition = gl_Position;\n"
876 "}\n"
877 "#endif\n"
878 "\n"
879 "#ifdef FRAGMENT_SHADER\n"
880 "uniform sampler2D Texture_Normal;\n"
881 "uniform sampler2D Texture_Refraction;\n"
882 "uniform sampler2D Texture_Reflection;\n"
883 "\n"
884 "uniform vec4 DistortScaleRefractReflect;\n"
885 "uniform vec4 ScreenScaleRefractReflect;\n"
886 "uniform vec4 ScreenCenterRefractReflect;\n"
887 "uniform vec4 RefractColor;\n"
888 "uniform vec4 ReflectColor;\n"
889 "uniform float ReflectFactor;\n"
890 "uniform float ReflectOffset;\n"
891 "\n"
892 "void main(void)\n"
893 "{\n"
894 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
895 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
896 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
897 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
898 "       vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
899 "       // FIXME temporary hack to detect the case that the reflection\n"
900 "       // gets blackened at edges due to leaving the area that contains actual\n"
901 "       // content.\n"
902 "       // Remove this 'ack once we have a better way to stop this thing from\n"
903 "       // 'appening.\n"
904 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
905 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
906 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
907 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
908 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
909 "       f       = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
910 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
911 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
912 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
913 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
914 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
915 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
916 "}\n"
917 "#endif\n"
918 "#else // !MODE_WATER\n"
919 "\n"
920 "\n"
921 "\n"
922 "\n"
923 "// common definitions between vertex shader and fragment shader:\n"
924 "\n"
925 "varying vec2 TexCoord;\n"
926 "#ifdef USEVERTEXTEXTUREBLEND\n"
927 "varying vec2 TexCoord2;\n"
928 "#endif\n"
929 "#ifdef USELIGHTMAP\n"
930 "varying vec2 TexCoordLightmap;\n"
931 "#endif\n"
932 "\n"
933 "#ifdef MODE_LIGHTSOURCE\n"
934 "varying vec3 CubeVector;\n"
935 "#endif\n"
936 "\n"
937 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
938 "varying vec3 LightVector;\n"
939 "#endif\n"
940 "\n"
941 "#ifdef USEEYEVECTOR\n"
942 "varying vec3 EyeVector;\n"
943 "#endif\n"
944 "#ifdef USEFOG\n"
945 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
946 "#endif\n"
947 "\n"
948 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
949 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
950 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
951 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
952 "#endif\n"
953 "\n"
954 "#ifdef USEREFLECTION\n"
955 "varying vec4 ModelViewProjectionPosition;\n"
956 "#endif\n"
957 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
958 "uniform vec3 LightPosition;\n"
959 "varying vec4 ModelViewPosition;\n"
960 "#endif\n"
961 "\n"
962 "#ifdef MODE_LIGHTSOURCE\n"
963 "uniform vec3 LightPosition;\n"
964 "#endif\n"
965 "uniform vec3 EyePosition;\n"
966 "#ifdef MODE_LIGHTDIRECTION\n"
967 "uniform vec3 LightDir;\n"
968 "#endif\n"
969 "uniform vec4 FogPlane;\n"
970 "\n"
971 "#ifdef USESHADOWMAPORTHO\n"
972 "varying vec3 ShadowMapTC;\n"
973 "#endif\n"
974 "\n"
975 "\n"
976 "\n"
977 "\n"
978 "\n"
979 "// 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"
980 "\n"
981 "// fragment shader specific:\n"
982 "#ifdef FRAGMENT_SHADER\n"
983 "\n"
984 "uniform sampler2D Texture_Normal;\n"
985 "uniform sampler2D Texture_Color;\n"
986 "uniform sampler2D Texture_Gloss;\n"
987 "#ifdef USEGLOW\n"
988 "uniform sampler2D Texture_Glow;\n"
989 "#endif\n"
990 "#ifdef USEVERTEXTEXTUREBLEND\n"
991 "uniform sampler2D Texture_SecondaryNormal;\n"
992 "uniform sampler2D Texture_SecondaryColor;\n"
993 "uniform sampler2D Texture_SecondaryGloss;\n"
994 "#ifdef USEGLOW\n"
995 "uniform sampler2D Texture_SecondaryGlow;\n"
996 "#endif\n"
997 "#endif\n"
998 "#ifdef USECOLORMAPPING\n"
999 "uniform sampler2D Texture_Pants;\n"
1000 "uniform sampler2D Texture_Shirt;\n"
1001 "#endif\n"
1002 "#ifdef USEFOG\n"
1003 "#ifdef USEFOGHEIGHTTEXTURE\n"
1004 "uniform sampler2D Texture_FogHeightTexture;\n"
1005 "#endif\n"
1006 "uniform sampler2D Texture_FogMask;\n"
1007 "#endif\n"
1008 "#ifdef USELIGHTMAP\n"
1009 "uniform sampler2D Texture_Lightmap;\n"
1010 "#endif\n"
1011 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1012 "uniform sampler2D Texture_Deluxemap;\n"
1013 "#endif\n"
1014 "#ifdef USEREFLECTION\n"
1015 "uniform sampler2D Texture_Reflection;\n"
1016 "#endif\n"
1017 "\n"
1018 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1019 "uniform sampler2D Texture_ScreenDepth;\n"
1020 "uniform sampler2D Texture_ScreenNormalMap;\n"
1021 "#endif\n"
1022 "#ifdef USEDEFERREDLIGHTMAP\n"
1023 "uniform sampler2D Texture_ScreenDiffuse;\n"
1024 "uniform sampler2D Texture_ScreenSpecular;\n"
1025 "#endif\n"
1026 "\n"
1027 "uniform myhalf3 Color_Pants;\n"
1028 "uniform myhalf3 Color_Shirt;\n"
1029 "uniform myhalf3 FogColor;\n"
1030 "\n"
1031 "#ifdef USEFOG\n"
1032 "uniform float FogRangeRecip;\n"
1033 "uniform float FogPlaneViewDist;\n"
1034 "uniform float FogHeightFade;\n"
1035 "vec3 FogVertex(vec3 surfacecolor)\n"
1036 "{\n"
1037 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1038 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1039 "       float fogfrac;\n"
1040 "#ifdef USEFOGHEIGHTTEXTURE\n"
1041 "       vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1042 "       fogfrac = fogheightpixel.a;\n"
1043 "       return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1044 "#else\n"
1045 "# ifdef USEFOGOUTSIDE\n"
1046 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1047 "# else\n"
1048 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1049 "# endif\n"
1050 "       return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1051 "#endif\n"
1052 "}\n"
1053 "#endif\n"
1054 "\n"
1055 "#ifdef USEOFFSETMAPPING\n"
1056 "uniform float OffsetMapping_Scale;\n"
1057 "vec2 OffsetMapping(vec2 TexCoord)\n"
1058 "{\n"
1059 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1060 "       // 14 sample relief mapping: linear search and then binary search\n"
1061 "       // this basically steps forward a small amount repeatedly until it finds\n"
1062 "       // itself inside solid, then jitters forward and back using decreasing\n"
1063 "       // amounts to find the impact\n"
1064 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1065 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1066 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1067 "       vec3 RT = vec3(TexCoord, 1);\n"
1068 "       OffsetVector *= 0.1;\n"
1069 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1070 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1071 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1072 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1073 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1074 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1075 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1076 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1077 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1078 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1079 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1080 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1081 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1082 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1083 "       return RT.xy;\n"
1084 "#else\n"
1085 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1086 "       // this basically moves forward the full distance, and then backs up based\n"
1087 "       // on height of samples\n"
1088 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1089 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1090 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1091 "       TexCoord += OffsetVector;\n"
1092 "       OffsetVector *= 0.333;\n"
1093 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1094 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1095 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1096 "       return TexCoord;\n"
1097 "#endif\n"
1098 "}\n"
1099 "#endif // USEOFFSETMAPPING\n"
1100 "\n"
1101 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1102 "uniform sampler2D Texture_Attenuation;\n"
1103 "uniform samplerCube Texture_Cube;\n"
1104 "#endif\n"
1105 "\n"
1106 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1107 "\n"
1108 "#ifdef USESHADOWMAPRECT\n"
1109 "# ifdef USESHADOWSAMPLER\n"
1110 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1111 "# else\n"
1112 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1113 "# endif\n"
1114 "#endif\n"
1115 "\n"
1116 "#ifdef USESHADOWMAP2D\n"
1117 "# ifdef USESHADOWSAMPLER\n"
1118 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1119 "# else\n"
1120 "uniform sampler2D Texture_ShadowMap2D;\n"
1121 "# endif\n"
1122 "#endif\n"
1123 "\n"
1124 "#ifdef USESHADOWMAPVSDCT\n"
1125 "uniform samplerCube Texture_CubeProjection;\n"
1126 "#endif\n"
1127 "\n"
1128 "#ifdef USESHADOWMAPCUBE\n"
1129 "# ifdef USESHADOWSAMPLER\n"
1130 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1131 "# else\n"
1132 "uniform samplerCube Texture_ShadowMapCube;\n"
1133 "# endif\n"
1134 "#endif\n"
1135 "\n"
1136 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1137 "uniform vec2 ShadowMap_TextureScale;\n"
1138 "uniform vec4 ShadowMap_Parameters;\n"
1139 "#endif\n"
1140 "\n"
1141 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1142 "# ifdef USESHADOWMAPORTHO\n"
1143 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1144 "# else\n"
1145 "#  ifdef USESHADOWMAPVSDCT\n"
1146 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1147 "{\n"
1148 "       vec3 adir = abs(dir);\n"
1149 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1150 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1151 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1152 "}\n"
1153 "#  else\n"
1154 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1155 "{\n"
1156 "       vec3 adir = abs(dir);\n"
1157 "       float ma = adir.z;\n"
1158 "       vec4 proj = vec4(dir, 2.5);\n"
1159 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1160 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1161 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1162 "       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"
1163 "}\n"
1164 "#  endif\n"
1165 "# endif\n"
1166 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1167 "\n"
1168 "#ifdef USESHADOWMAPCUBE\n"
1169 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1170 "{\n"
1171 "       vec3 adir = abs(dir);\n"
1172 "       return vec4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
1173 "}\n"
1174 "#endif\n"
1175 "\n"
1176 "# ifdef USESHADOWMAPRECT\n"
1177 "float ShadowMapCompare(vec3 dir)\n"
1178 "{\n"
1179 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1180 "       float f;\n"
1181 "#  ifdef USESHADOWSAMPLER\n"
1182 "\n"
1183 "#    ifdef USESHADOWMAPPCF\n"
1184 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1185 "       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"
1186 "#    else\n"
1187 "       f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1188 "#    endif\n"
1189 "\n"
1190 "#  else\n"
1191 "\n"
1192 "#    ifdef USESHADOWMAPPCF\n"
1193 "#      if USESHADOWMAPPCF > 1\n"
1194 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1195 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1196 "       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"
1197 "       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"
1198 "       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"
1199 "       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"
1200 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1201 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1202 "#      else\n"
1203 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1204 "       vec2 offset = fract(shadowmaptc.xy);\n"
1205 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1206 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1207 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1208 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1209 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1210 "#      endif\n"
1211 "#    else\n"
1212 "       f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1213 "#    endif\n"
1214 "\n"
1215 "#  endif\n"
1216 "#  ifdef USESHADOWMAPORTHO\n"
1217 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1218 "#  else\n"
1219 "       return f;\n"
1220 "#  endif\n"
1221 "}\n"
1222 "# endif\n"
1223 "\n"
1224 "# ifdef USESHADOWMAP2D\n"
1225 "float ShadowMapCompare(vec3 dir)\n"
1226 "{\n"
1227 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1228 "       float f;\n"
1229 "\n"
1230 "#  ifdef USESHADOWSAMPLER\n"
1231 "#    ifdef USESHADOWMAPPCF\n"
1232 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1233 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1234 "       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"
1235 "#    else\n"
1236 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1237 "#    endif\n"
1238 "#  else\n"
1239 "#    ifdef USESHADOWMAPPCF\n"
1240 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1241 "#      ifdef GL_ARB_texture_gather\n"
1242 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1243 "#      else\n"
1244 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1245 "#      endif\n"
1246 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1247 "#      if USESHADOWMAPPCF > 1\n"
1248 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1249 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1250 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1251 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
1252 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
1253 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
1254 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
1255 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
1256 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
1257 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
1258 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
1259 "       locols.yz += group2.ab;\n"
1260 "       hicols.yz += group8.rg;\n"
1261 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1262 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1263 "                               mix(locols, hicols, offset.y);\n"
1264 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1265 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1266 "       f = dot(cols, vec4(1.0/25.0));\n"
1267 "#      else\n"
1268 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1269 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1270 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1271 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1272 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1273 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1274 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1275 "#      endif\n"
1276 "#     else\n"
1277 "#      ifdef GL_EXT_gpu_shader4\n"
1278 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1279 "#      else\n"
1280 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1281 "#      endif\n"
1282 "#      if USESHADOWMAPPCF > 1\n"
1283 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1284 "       center *= ShadowMap_TextureScale;\n"
1285 "       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"
1286 "       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"
1287 "       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"
1288 "       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"
1289 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1290 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1291 "#      else\n"
1292 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1293 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1294 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1295 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1296 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1297 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1298 "#      endif\n"
1299 "#     endif\n"
1300 "#    else\n"
1301 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1302 "#    endif\n"
1303 "#  endif\n"
1304 "#  ifdef USESHADOWMAPORTHO\n"
1305 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1306 "#  else\n"
1307 "       return f;\n"
1308 "#  endif\n"
1309 "}\n"
1310 "# endif\n"
1311 "\n"
1312 "# ifdef USESHADOWMAPCUBE\n"
1313 "float ShadowMapCompare(vec3 dir)\n"
1314 "{\n"
1315 "       // apply depth texture cubemap as light filter\n"
1316 "       vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1317 "       float f;\n"
1318 "#  ifdef USESHADOWSAMPLER\n"
1319 "       f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1320 "#  else\n"
1321 "       f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1322 "#  endif\n"
1323 "       return f;\n"
1324 "}\n"
1325 "# endif\n"
1326 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1327 "#endif // FRAGMENT_SHADER\n"
1328 "\n"
1329 "\n"
1330 "\n"
1331 "\n"
1332 "#ifdef MODE_DEFERREDGEOMETRY\n"
1333 "#ifdef VERTEX_SHADER\n"
1334 "uniform mat4 TexMatrix;\n"
1335 "#ifdef USEVERTEXTEXTUREBLEND\n"
1336 "uniform mat4 BackgroundTexMatrix;\n"
1337 "#endif\n"
1338 "uniform mat4 ModelViewMatrix;\n"
1339 "void main(void)\n"
1340 "{\n"
1341 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1342 "#ifdef USEVERTEXTEXTUREBLEND\n"
1343 "       gl_FrontColor = gl_Color;\n"
1344 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1345 "#endif\n"
1346 "\n"
1347 "       // transform unnormalized eye direction into tangent space\n"
1348 "#ifdef USEOFFSETMAPPING\n"
1349 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1350 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1351 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1352 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1353 "#endif\n"
1354 "\n"
1355 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1356 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1357 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1358 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1359 "}\n"
1360 "#endif // VERTEX_SHADER\n"
1361 "\n"
1362 "#ifdef FRAGMENT_SHADER\n"
1363 "void main(void)\n"
1364 "{\n"
1365 "#ifdef USEOFFSETMAPPING\n"
1366 "       // apply offsetmapping\n"
1367 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1368 "#define TexCoord TexCoordOffset\n"
1369 "#endif\n"
1370 "\n"
1371 "#ifdef USEALPHAKILL\n"
1372 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1373 "               discard;\n"
1374 "#endif\n"
1375 "\n"
1376 "#ifdef USEVERTEXTEXTUREBLEND\n"
1377 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1378 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1379 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1380 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1381 "#endif\n"
1382 "\n"
1383 "#ifdef USEVERTEXTEXTUREBLEND\n"
1384 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1385 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1386 "#else\n"
1387 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1388 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1389 "#endif\n"
1390 "\n"
1391 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1392 "}\n"
1393 "#endif // FRAGMENT_SHADER\n"
1394 "#else // !MODE_DEFERREDGEOMETRY\n"
1395 "\n"
1396 "\n"
1397 "\n"
1398 "\n"
1399 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1400 "#ifdef VERTEX_SHADER\n"
1401 "uniform mat4 ModelViewMatrix;\n"
1402 "void main(void)\n"
1403 "{\n"
1404 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1405 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1406 "}\n"
1407 "#endif // VERTEX_SHADER\n"
1408 "\n"
1409 "#ifdef FRAGMENT_SHADER\n"
1410 "uniform mat4 ViewToLight;\n"
1411 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1412 "uniform vec2 ScreenToDepth;\n"
1413 "uniform myhalf3 DeferredColor_Ambient;\n"
1414 "uniform myhalf3 DeferredColor_Diffuse;\n"
1415 "#ifdef USESPECULAR\n"
1416 "uniform myhalf3 DeferredColor_Specular;\n"
1417 "uniform myhalf SpecularPower;\n"
1418 "#endif\n"
1419 "uniform myhalf2 PixelToScreenTexCoord;\n"
1420 "void main(void)\n"
1421 "{\n"
1422 "       // calculate viewspace pixel position\n"
1423 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1424 "       vec3 position;\n"
1425 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1426 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1427 "       // decode viewspace pixel normal\n"
1428 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1429 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1430 "       // surfacenormal = pixel normal in viewspace\n"
1431 "       // LightVector = pixel to light in viewspace\n"
1432 "       // CubeVector = position in lightspace\n"
1433 "       // eyevector = pixel to view in viewspace\n"
1434 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1435 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1436 "#ifdef USEDIFFUSE\n"
1437 "       // calculate diffuse shading\n"
1438 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1439 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1440 "#endif\n"
1441 "#ifdef USESPECULAR\n"
1442 "       // calculate directional shading\n"
1443 "       vec3 eyevector = position * -1.0;\n"
1444 "#  ifdef USEEXACTSPECULARMATH\n"
1445 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1446 "#  else\n"
1447 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1448 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1449 "#  endif\n"
1450 "#endif\n"
1451 "\n"
1452 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1453 "       fade *= ShadowMapCompare(CubeVector);\n"
1454 "#endif\n"
1455 "\n"
1456 "#ifdef USEDIFFUSE\n"
1457 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1458 "#else\n"
1459 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1460 "#endif\n"
1461 "#ifdef USESPECULAR\n"
1462 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1463 "#else\n"
1464 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1465 "#endif\n"
1466 "\n"
1467 "# ifdef USECUBEFILTER\n"
1468 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1469 "       gl_FragData[0].rgb *= cubecolor;\n"
1470 "       gl_FragData[1].rgb *= cubecolor;\n"
1471 "# endif\n"
1472 "}\n"
1473 "#endif // FRAGMENT_SHADER\n"
1474 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1475 "\n"
1476 "\n"
1477 "\n"
1478 "\n"
1479 "#ifdef VERTEX_SHADER\n"
1480 "uniform mat4 TexMatrix;\n"
1481 "#ifdef USEVERTEXTEXTUREBLEND\n"
1482 "uniform mat4 BackgroundTexMatrix;\n"
1483 "#endif\n"
1484 "#ifdef MODE_LIGHTSOURCE\n"
1485 "uniform mat4 ModelToLight;\n"
1486 "#endif\n"
1487 "#ifdef USESHADOWMAPORTHO\n"
1488 "uniform mat4 ShadowMapMatrix;\n"
1489 "#endif\n"
1490 "void main(void)\n"
1491 "{\n"
1492 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1493 "       gl_FrontColor = gl_Color;\n"
1494 "#endif\n"
1495 "       // copy the surface texcoord\n"
1496 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1497 "#ifdef USEVERTEXTEXTUREBLEND\n"
1498 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1499 "#endif\n"
1500 "#ifdef USELIGHTMAP\n"
1501 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1502 "#endif\n"
1503 "\n"
1504 "#ifdef MODE_LIGHTSOURCE\n"
1505 "       // transform vertex position into light attenuation/cubemap space\n"
1506 "       // (-1 to +1 across the light box)\n"
1507 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1508 "\n"
1509 "# ifdef USEDIFFUSE\n"
1510 "       // transform unnormalized light direction into tangent space\n"
1511 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1512 "       //  normalize it per pixel)\n"
1513 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1514 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1515 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1516 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1517 "# endif\n"
1518 "#endif\n"
1519 "\n"
1520 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1521 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1522 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1523 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1524 "#endif\n"
1525 "\n"
1526 "       // transform unnormalized eye direction into tangent space\n"
1527 "#ifdef USEEYEVECTOR\n"
1528 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1529 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1530 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1531 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1532 "#endif\n"
1533 "\n"
1534 "#ifdef USEFOG\n"
1535 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1536 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1537 "#endif\n"
1538 "\n"
1539 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1540 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1541 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1542 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1543 "#endif\n"
1544 "\n"
1545 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1546 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1547 "\n"
1548 "#ifdef USESHADOWMAPORTHO\n"
1549 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1550 "#endif\n"
1551 "\n"
1552 "#ifdef USEREFLECTION\n"
1553 "       ModelViewProjectionPosition = gl_Position;\n"
1554 "#endif\n"
1555 "}\n"
1556 "#endif // VERTEX_SHADER\n"
1557 "\n"
1558 "\n"
1559 "\n"
1560 "\n"
1561 "#ifdef FRAGMENT_SHADER\n"
1562 "#ifdef USEDEFERREDLIGHTMAP\n"
1563 "uniform myhalf2 PixelToScreenTexCoord;\n"
1564 "uniform myhalf3 DeferredMod_Diffuse;\n"
1565 "uniform myhalf3 DeferredMod_Specular;\n"
1566 "#endif\n"
1567 "uniform myhalf3 Color_Ambient;\n"
1568 "uniform myhalf3 Color_Diffuse;\n"
1569 "uniform myhalf3 Color_Specular;\n"
1570 "uniform myhalf SpecularPower;\n"
1571 "#ifdef USEGLOW\n"
1572 "uniform myhalf3 Color_Glow;\n"
1573 "#endif\n"
1574 "uniform myhalf Alpha;\n"
1575 "#ifdef USEREFLECTION\n"
1576 "uniform vec4 DistortScaleRefractReflect;\n"
1577 "uniform vec4 ScreenScaleRefractReflect;\n"
1578 "uniform vec4 ScreenCenterRefractReflect;\n"
1579 "uniform myhalf4 ReflectColor;\n"
1580 "#endif\n"
1581 "#ifdef USEREFLECTCUBE\n"
1582 "uniform mat4 ModelToReflectCube;\n"
1583 "uniform sampler2D Texture_ReflectMask;\n"
1584 "uniform samplerCube Texture_ReflectCube;\n"
1585 "#endif\n"
1586 "#ifdef MODE_LIGHTDIRECTION\n"
1587 "uniform myhalf3 LightColor;\n"
1588 "#endif\n"
1589 "#ifdef MODE_LIGHTSOURCE\n"
1590 "uniform myhalf3 LightColor;\n"
1591 "#endif\n"
1592 "void main(void)\n"
1593 "{\n"
1594 "#ifdef USEOFFSETMAPPING\n"
1595 "       // apply offsetmapping\n"
1596 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1597 "#define TexCoord TexCoordOffset\n"
1598 "#endif\n"
1599 "\n"
1600 "       // combine the diffuse textures (base, pants, shirt)\n"
1601 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1602 "#ifdef USEALPHAKILL\n"
1603 "       if (color.a < 0.5)\n"
1604 "               discard;\n"
1605 "#endif\n"
1606 "       color.a *= Alpha;\n"
1607 "#ifdef USECOLORMAPPING\n"
1608 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1609 "#endif\n"
1610 "#ifdef USEVERTEXTEXTUREBLEND\n"
1611 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1612 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1613 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1614 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1615 "       color.a = 1.0;\n"
1616 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1617 "#endif\n"
1618 "\n"
1619 "       // get the surface normal\n"
1620 "#ifdef USEVERTEXTEXTUREBLEND\n"
1621 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1622 "#else\n"
1623 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1624 "#endif\n"
1625 "\n"
1626 "       // get the material colors\n"
1627 "       myhalf3 diffusetex = color.rgb;\n"
1628 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1629 "# ifdef USEVERTEXTEXTUREBLEND\n"
1630 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1631 "# else\n"
1632 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1633 "# endif\n"
1634 "#endif\n"
1635 "\n"
1636 "#ifdef USEREFLECTCUBE\n"
1637 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1638 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1639 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1640 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1641 "#endif\n"
1642 "\n"
1643 "\n"
1644 "\n"
1645 "\n"
1646 "#ifdef MODE_LIGHTSOURCE\n"
1647 "       // light source\n"
1648 "#ifdef USEDIFFUSE\n"
1649 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1650 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1651 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1652 "#ifdef USESPECULAR\n"
1653 "#ifdef USEEXACTSPECULARMATH\n"
1654 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1655 "#else\n"
1656 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1657 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1658 "#endif\n"
1659 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1660 "#endif\n"
1661 "#else\n"
1662 "       color.rgb = diffusetex * Color_Ambient;\n"
1663 "#endif\n"
1664 "       color.rgb *= LightColor;\n"
1665 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1666 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1667 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1668 "#endif\n"
1669 "# ifdef USECUBEFILTER\n"
1670 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1671 "# endif\n"
1672 "#endif // MODE_LIGHTSOURCE\n"
1673 "\n"
1674 "\n"
1675 "\n"
1676 "\n"
1677 "#ifdef MODE_LIGHTDIRECTION\n"
1678 "#define SHADING\n"
1679 "#ifdef USEDIFFUSE\n"
1680 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1681 "#endif\n"
1682 "#define lightcolor LightColor\n"
1683 "#endif // MODE_LIGHTDIRECTION\n"
1684 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1685 "#define SHADING\n"
1686 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1687 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1688 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1689 "       // convert modelspace light vector to tangentspace\n"
1690 "       myhalf3 lightnormal;\n"
1691 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1692 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1693 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1694 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1695 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1696 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1697 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1698 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1699 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1700 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1701 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1702 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1703 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1704 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1705 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1706 "#define SHADING\n"
1707 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1708 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1709 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1710 "#endif\n"
1711 "\n"
1712 "\n"
1713 "\n"
1714 "\n"
1715 "#ifdef MODE_LIGHTMAP\n"
1716 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1717 "#endif // MODE_LIGHTMAP\n"
1718 "#ifdef MODE_VERTEXCOLOR\n"
1719 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1720 "#endif // MODE_VERTEXCOLOR\n"
1721 "#ifdef MODE_FLATCOLOR\n"
1722 "       color.rgb = diffusetex * Color_Ambient;\n"
1723 "#endif // MODE_FLATCOLOR\n"
1724 "\n"
1725 "\n"
1726 "\n"
1727 "\n"
1728 "#ifdef SHADING\n"
1729 "# ifdef USEDIFFUSE\n"
1730 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1731 "#  ifdef USESPECULAR\n"
1732 "#   ifdef USEEXACTSPECULARMATH\n"
1733 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1734 "#   else\n"
1735 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1736 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1737 "#   endif\n"
1738 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1739 "#  else\n"
1740 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1741 "#  endif\n"
1742 "# else\n"
1743 "       color.rgb = diffusetex * Color_Ambient;\n"
1744 "# endif\n"
1745 "#endif\n"
1746 "\n"
1747 "#ifdef USESHADOWMAPORTHO\n"
1748 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1749 "#endif\n"
1750 "\n"
1751 "#ifdef USEDEFERREDLIGHTMAP\n"
1752 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1753 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1754 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1755 "#endif\n"
1756 "\n"
1757 "#ifdef USEGLOW\n"
1758 "#ifdef USEVERTEXTEXTUREBLEND\n"
1759 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1760 "#else\n"
1761 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1762 "#endif\n"
1763 "#endif\n"
1764 "\n"
1765 "#ifdef USEFOG\n"
1766 "       color.rgb = FogVertex(color.rgb);\n"
1767 "#endif\n"
1768 "\n"
1769 "       // 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"
1770 "#ifdef USEREFLECTION\n"
1771 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1772 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1773 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1774 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1775 "       // FIXME temporary hack to detect the case that the reflection\n"
1776 "       // gets blackened at edges due to leaving the area that contains actual\n"
1777 "       // content.\n"
1778 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1779 "       // 'appening.\n"
1780 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1781 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1782 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1783 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1784 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1785 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1786 "#endif\n"
1787 "\n"
1788 "       gl_FragColor = vec4(color);\n"
1789 "}\n"
1790 "#endif // FRAGMENT_SHADER\n"
1791 "\n"
1792 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1793 "#endif // !MODE_DEFERREDGEOMETRY\n"
1794 "#endif // !MODE_WATER\n"
1795 "#endif // !MODE_REFRACTION\n"
1796 "#endif // !MODE_BLOOMBLUR\n"
1797 "#endif // !MODE_GENERIC\n"
1798 "#endif // !MODE_POSTPROCESS\n"
1799 "#endif // !MODE_SHOWDEPTH\n"
1800 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1801 ;
1802
1803 /*
1804 =========================================================================================================================================================
1805
1806
1807
1808 =========================================================================================================================================================
1809
1810
1811
1812 =========================================================================================================================================================
1813
1814
1815
1816 =========================================================================================================================================================
1817
1818
1819
1820 =========================================================================================================================================================
1821
1822
1823
1824 =========================================================================================================================================================
1825
1826
1827
1828 =========================================================================================================================================================
1829 */
1830
1831 const char *builtincgshaderstring =
1832 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1833 "// written by Forest 'LordHavoc' Hale\n"
1834 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1835 "\n"
1836 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1837 "#if defined(USEREFLECTION)\n"
1838 "#undef USESHADOWMAPORTHO\n"
1839 "#endif\n"
1840 "\n"
1841 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1842 "# define USEFOG\n"
1843 "#endif\n"
1844 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1845 "#define USELIGHTMAP\n"
1846 "#endif\n"
1847 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
1848 "#define USEEYEVECTOR\n"
1849 "#endif\n"
1850 "\n"
1851 "#ifdef FRAGMENT_SHADER\n"
1852 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1853 "#endif\n"
1854 "\n"
1855 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1856 "#ifdef VERTEX_SHADER\n"
1857 "void main\n"
1858 "(\n"
1859 "float4 gl_Vertex : POSITION,\n"
1860 "uniform float4x4 ModelViewProjectionMatrix,\n"
1861 "out float4 gl_Position : POSITION\n"
1862 ")\n"
1863 "{\n"
1864 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1865 "}\n"
1866 "#endif\n"
1867 "#else // !MODE_DEPTH_ORSHADOW\n"
1868 "\n"
1869 "\n"
1870 "\n"
1871 "\n"
1872 "#ifdef MODE_SHOWDEPTH\n"
1873 "#ifdef VERTEX_SHADER\n"
1874 "void main\n"
1875 "(\n"
1876 "float4 gl_Vertex : POSITION,\n"
1877 "uniform float4x4 ModelViewProjectionMatrix,\n"
1878 "out float4 gl_Position : POSITION,\n"
1879 "out float4 gl_FrontColor : COLOR0\n"
1880 ")\n"
1881 "{\n"
1882 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1883 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1884 "}\n"
1885 "#endif\n"
1886 "\n"
1887 "#ifdef FRAGMENT_SHADER\n"
1888 "void main\n"
1889 "(\n"
1890 "float4 gl_FrontColor : COLOR0,\n"
1891 "out float4 gl_FragColor : COLOR\n"
1892 ")\n"
1893 "{\n"
1894 "       gl_FragColor = gl_FrontColor;\n"
1895 "}\n"
1896 "#endif\n"
1897 "#else // !MODE_SHOWDEPTH\n"
1898 "\n"
1899 "\n"
1900 "\n"
1901 "\n"
1902 "#ifdef MODE_POSTPROCESS\n"
1903 "\n"
1904 "#ifdef VERTEX_SHADER\n"
1905 "void main\n"
1906 "(\n"
1907 "float4 gl_Vertex : POSITION,\n"
1908 "uniform float4x4 ModelViewProjectionMatrix,\n"
1909 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1910 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1911 "out float4 gl_Position : POSITION,\n"
1912 "out float2 TexCoord1 : TEXCOORD0,\n"
1913 "out float2 TexCoord2 : TEXCOORD1\n"
1914 ")\n"
1915 "{\n"
1916 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1917 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1918 "#ifdef USEBLOOM\n"
1919 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1920 "#endif\n"
1921 "}\n"
1922 "#endif\n"
1923 "\n"
1924 "#ifdef FRAGMENT_SHADER\n"
1925 "void main\n"
1926 "(\n"
1927 "float2 TexCoord1 : TEXCOORD0,\n"
1928 "float2 TexCoord2 : TEXCOORD1,\n"
1929 "uniform sampler2D Texture_First,\n"
1930 "#ifdef USEBLOOM\n"
1931 "uniform sampler2D Texture_Second,\n"
1932 "#endif\n"
1933 "#ifdef USEGAMMARAMPS\n"
1934 "uniform sampler2D Texture_GammaRamps,\n"
1935 "#endif\n"
1936 "#ifdef USESATURATION\n"
1937 "uniform float Saturation,\n"
1938 "#endif\n"
1939 "#ifdef USEVIEWTINT\n"
1940 "uniform float4 ViewTintColor,\n"
1941 "#endif\n"
1942 "uniform float4 UserVec1,\n"
1943 "uniform float4 UserVec2,\n"
1944 "uniform float4 UserVec3,\n"
1945 "uniform float4 UserVec4,\n"
1946 "uniform float ClientTime,\n"
1947 "uniform float2 PixelSize,\n"
1948 "out float4 gl_FragColor : COLOR\n"
1949 ")\n"
1950 "{\n"
1951 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1952 "#ifdef USEBLOOM\n"
1953 "       gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
1954 "#endif\n"
1955 "#ifdef USEVIEWTINT\n"
1956 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1957 "#endif\n"
1958 "\n"
1959 "#ifdef USEPOSTPROCESSING\n"
1960 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1961 "// 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"
1962 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1963 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1964 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1965 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
1966 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
1967 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
1968 "#endif\n"
1969 "\n"
1970 "#ifdef USESATURATION\n"
1971 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
1972 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
1973 "       //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
1974 "       gl_FragColor.rgb = lerp(float3(y), gl_FragColor.rgb, Saturation);\n"
1975 "#endif\n"
1976 "\n"
1977 "#ifdef USEGAMMARAMPS\n"
1978 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
1979 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
1980 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
1981 "#endif\n"
1982 "}\n"
1983 "#endif\n"
1984 "#else // !MODE_POSTPROCESS\n"
1985 "\n"
1986 "\n"
1987 "\n"
1988 "\n"
1989 "#ifdef MODE_GENERIC\n"
1990 "#ifdef VERTEX_SHADER\n"
1991 "void main\n"
1992 "(\n"
1993 "float4 gl_Vertex : POSITION,\n"
1994 "uniform float4x4 ModelViewProjectionMatrix,\n"
1995 "float4 gl_Color : COLOR0,\n"
1996 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1997 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1998 "out float4 gl_Position : POSITION,\n"
1999 "out float4 gl_FrontColor : COLOR,\n"
2000 "out float2 TexCoord1 : TEXCOORD0,\n"
2001 "out float2 TexCoord2 : TEXCOORD1\n"
2002 ")\n"
2003 "{\n"
2004 "       gl_FrontColor = gl_Color;\n"
2005 "#ifdef USEDIFFUSE\n"
2006 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2007 "#endif\n"
2008 "#ifdef USESPECULAR\n"
2009 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
2010 "#endif\n"
2011 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2012 "}\n"
2013 "#endif\n"
2014 "\n"
2015 "#ifdef FRAGMENT_SHADER\n"
2016 "\n"
2017 "void main\n"
2018 "(\n"
2019 "float4 gl_FrontColor : COLOR,\n"
2020 "float2 TexCoord1 : TEXCOORD0,\n"
2021 "float2 TexCoord2 : TEXCOORD1,\n"
2022 "#ifdef USEDIFFUSE\n"
2023 "uniform sampler2D Texture_First,\n"
2024 "#endif\n"
2025 "#ifdef USESPECULAR\n"
2026 "uniform sampler2D Texture_Second,\n"
2027 "#endif\n"
2028 "out float4 gl_FragColor : COLOR\n"
2029 ")\n"
2030 "{\n"
2031 "       gl_FragColor = gl_FrontColor;\n"
2032 "#ifdef USEDIFFUSE\n"
2033 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2034 "#endif\n"
2035 "\n"
2036 "#ifdef USESPECULAR\n"
2037 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2038 "# ifdef USECOLORMAPPING\n"
2039 "       gl_FragColor *= tex2;\n"
2040 "# endif\n"
2041 "# ifdef USEGLOW\n"
2042 "       gl_FragColor += tex2;\n"
2043 "# endif\n"
2044 "# ifdef USEVERTEXTEXTUREBLEND\n"
2045 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2046 "# endif\n"
2047 "#endif\n"
2048 "}\n"
2049 "#endif\n"
2050 "#else // !MODE_GENERIC\n"
2051 "\n"
2052 "\n"
2053 "\n"
2054 "\n"
2055 "#ifdef MODE_BLOOMBLUR\n"
2056 "#ifdef VERTEX_SHADER\n"
2057 "void main\n"
2058 "(\n"
2059 "float4 gl_Vertex : POSITION,\n"
2060 "uniform float4x4 ModelViewProjectionMatrix,\n"
2061 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2062 "out float4 gl_Position : POSITION,\n"
2063 "out float2 TexCoord : TEXCOORD0\n"
2064 ")\n"
2065 "{\n"
2066 "       TexCoord = gl_MultiTexCoord0.xy;\n"
2067 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2068 "}\n"
2069 "#endif\n"
2070 "\n"
2071 "#ifdef FRAGMENT_SHADER\n"
2072 "\n"
2073 "void main\n"
2074 "(\n"
2075 "float2 TexCoord : TEXCOORD0,\n"
2076 "uniform sampler2D Texture_First,\n"
2077 "uniform float4 BloomBlur_Parameters,\n"
2078 "out float4 gl_FragColor : COLOR\n"
2079 ")\n"
2080 "{\n"
2081 "       int i;\n"
2082 "       float2 tc = TexCoord;\n"
2083 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2084 "       tc += BloomBlur_Parameters.xy;\n"
2085 "       for (i = 1;i < SAMPLES;i++)\n"
2086 "       {\n"
2087 "               color += tex2D(Texture_First, tc).rgb;\n"
2088 "               tc += BloomBlur_Parameters.xy;\n"
2089 "       }\n"
2090 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2091 "}\n"
2092 "#endif\n"
2093 "#else // !MODE_BLOOMBLUR\n"
2094 "#ifdef MODE_REFRACTION\n"
2095 "#ifdef VERTEX_SHADER\n"
2096 "void main\n"
2097 "(\n"
2098 "float4 gl_Vertex : POSITION,\n"
2099 "uniform float4x4 ModelViewProjectionMatrix,\n"
2100 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2101 "uniform float4x4 TexMatrix,\n"
2102 "uniform float3 EyePosition,\n"
2103 "out float4 gl_Position : POSITION,\n"
2104 "out float2 TexCoord : TEXCOORD0,\n"
2105 "out float3 EyeVector : TEXCOORD1,\n"
2106 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2107 ")\n"
2108 "{\n"
2109 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2110 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2111 "       ModelViewProjectionPosition = gl_Position;\n"
2112 "}\n"
2113 "#endif\n"
2114 "\n"
2115 "#ifdef FRAGMENT_SHADER\n"
2116 "void main\n"
2117 "(\n"
2118 "float2 TexCoord : TEXCOORD0,\n"
2119 "float3 EyeVector : TEXCOORD1,\n"
2120 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2121 "uniform sampler2D Texture_Normal,\n"
2122 "uniform sampler2D Texture_Refraction,\n"
2123 "uniform sampler2D Texture_Reflection,\n"
2124 "uniform float4 DistortScaleRefractReflect,\n"
2125 "uniform float4 ScreenScaleRefractReflect,\n"
2126 "uniform float4 ScreenCenterRefractReflect,\n"
2127 "uniform float4 RefractColor,\n"
2128 "out float4 gl_FragColor : COLOR\n"
2129 ")\n"
2130 "{\n"
2131 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2132 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2133 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2134 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
2135 "       // FIXME temporary hack to detect the case that the reflection\n"
2136 "       // gets blackened at edges due to leaving the area that contains actual\n"
2137 "       // content.\n"
2138 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2139 "       // 'appening.\n"
2140 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2141 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2142 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2143 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2144 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2145 "       gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2146 "}\n"
2147 "#endif\n"
2148 "#else // !MODE_REFRACTION\n"
2149 "\n"
2150 "\n"
2151 "\n"
2152 "\n"
2153 "#ifdef MODE_WATER\n"
2154 "#ifdef VERTEX_SHADER\n"
2155 "\n"
2156 "void main\n"
2157 "(\n"
2158 "float4 gl_Vertex : POSITION,\n"
2159 "uniform float4x4 ModelViewProjectionMatrix,\n"
2160 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2161 "uniform float4x4 TexMatrix,\n"
2162 "uniform float3 EyePosition,\n"
2163 "out float4 gl_Position : POSITION,\n"
2164 "out float2 TexCoord : TEXCOORD0,\n"
2165 "out float3 EyeVector : TEXCOORD1,\n"
2166 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2167 ")\n"
2168 "{\n"
2169 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2170 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2171 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2172 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2173 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2174 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2175 "       ModelViewProjectionPosition = gl_Position;\n"
2176 "}\n"
2177 "#endif\n"
2178 "\n"
2179 "#ifdef FRAGMENT_SHADER\n"
2180 "void main\n"
2181 "(\n"
2182 "float2 TexCoord : TEXCOORD0,\n"
2183 "float3 EyeVector : TEXCOORD1,\n"
2184 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2185 "uniform sampler2D Texture_Normal,\n"
2186 "uniform sampler2D Texture_Refraction,\n"
2187 "uniform sampler2D Texture_Reflection,\n"
2188 "uniform float4 DistortScaleRefractReflect,\n"
2189 "uniform float4 ScreenScaleRefractReflect,\n"
2190 "uniform float4 ScreenCenterRefractReflect,\n"
2191 "uniform float4 RefractColor,\n"
2192 "uniform float4 ReflectColor,\n"
2193 "uniform float ReflectFactor,\n"
2194 "uniform float ReflectOffset,\n"
2195 "out float4 gl_FragColor : COLOR\n"
2196 ")\n"
2197 "{\n"
2198 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2199 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2200 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2201 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xyxy * DistortScaleRefractReflect;\n"
2202 "       // FIXME temporary hack to detect the case that the reflection\n"
2203 "       // gets blackened at edges due to leaving the area that contains actual\n"
2204 "       // content.\n"
2205 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2206 "       // 'appening.\n"
2207 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2208 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2209 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2210 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2211 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2212 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2213 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2214 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2215 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2216 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2217 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2218 "       gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2219 "}\n"
2220 "#endif\n"
2221 "#else // !MODE_WATER\n"
2222 "\n"
2223 "\n"
2224 "\n"
2225 "\n"
2226 "// 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"
2227 "\n"
2228 "// fragment shader specific:\n"
2229 "#ifdef FRAGMENT_SHADER\n"
2230 "\n"
2231 "#ifdef USEFOG\n"
2232 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask, sampler2D Texture_FogHeightTexture)\n"
2233 "{\n"
2234 "       float fogfrac;\n"
2235 "#ifdef USEFOGHEIGHTTEXTURE\n"
2236 "       float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2237 "       fogfrac = fogheightpixel.a;\n"
2238 "       return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2239 "#else\n"
2240 "# ifdef USEFOGOUTSIDE\n"
2241 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2242 "# else\n"
2243 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2244 "# endif\n"
2245 "       return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2246 "#endif\n"
2247 "}\n"
2248 "#endif\n"
2249 "\n"
2250 "#ifdef USEOFFSETMAPPING\n"
2251 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler2D Texture_Normal)\n"
2252 "{\n"
2253 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2254 "       // 14 sample relief mapping: linear search and then binary search\n"
2255 "       // this basically steps forward a small amount repeatedly until it finds\n"
2256 "       // itself inside solid, then jitters forward and back using decreasing\n"
2257 "       // amounts to find the impact\n"
2258 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2259 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2260 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2261 "       float3 RT = float3(TexCoord, 1);\n"
2262 "       OffsetVector *= 0.1;\n"
2263 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2264 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2265 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2266 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2267 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2268 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2269 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2270 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2271 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2272 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2273 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2274 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2275 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2276 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2277 "       return RT.xy;\n"
2278 "#else\n"
2279 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2280 "       // this basically moves forward the full distance, and then backs up based\n"
2281 "       // on height of samples\n"
2282 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2283 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2284 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2285 "       TexCoord += OffsetVector;\n"
2286 "       OffsetVector *= 0.333;\n"
2287 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2288 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2289 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2290 "       return TexCoord;\n"
2291 "#endif\n"
2292 "}\n"
2293 "#endif // USEOFFSETMAPPING\n"
2294 "\n"
2295 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2296 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2297 "# ifdef USESHADOWMAPORTHO\n"
2298 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2299 "# else\n"
2300 "#  ifdef USESHADOWMAPVSDCT\n"
2301 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2302 "{\n"
2303 "       float3 adir = abs(dir);\n"
2304 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2305 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2306 "       return float3(lerp(dir.xy, proj.xy, dir.zz) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2307 "}\n"
2308 "#  else\n"
2309 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2310 "{\n"
2311 "       float3 adir = abs(dir);\n"
2312 "       float ma = adir.z;\n"
2313 "       float4 proj = float4(dir, 2.5);\n"
2314 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2315 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2316 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2317 "       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"
2318 "}\n"
2319 "#  endif\n"
2320 "# endif\n"
2321 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2322 "\n"
2323 "#ifdef USESHADOWMAPCUBE\n"
2324 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2325 "{\n"
2326 "    float3 adir = abs(dir);\n"
2327 "    return float4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
2328 "}\n"
2329 "#endif\n"
2330 "\n"
2331 "# ifdef USESHADOWMAPRECT\n"
2332 "#ifdef USESHADOWMAPVSDCT\n"
2333 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2334 "#else\n"
2335 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2336 "#endif\n"
2337 "{\n"
2338 "#ifdef USESHADOWMAPVSDCT\n"
2339 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2340 "#else\n"
2341 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2342 "#endif\n"
2343 "       float f;\n"
2344 "#  ifdef USESHADOWSAMPLER\n"
2345 "\n"
2346 "#    ifdef USESHADOWMAPPCF\n"
2347 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2348 "    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"
2349 "#    else\n"
2350 "    f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2351 "#    endif\n"
2352 "\n"
2353 "#  else\n"
2354 "\n"
2355 "#    ifdef USESHADOWMAPPCF\n"
2356 "#      if USESHADOWMAPPCF > 1\n"
2357 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2358 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2359 "    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"
2360 "    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"
2361 "    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"
2362 "    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"
2363 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2364 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2365 "#      else\n"
2366 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2367 "    float2 offset = frac(shadowmaptc.xy);\n"
2368 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2369 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2370 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2371 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2372 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2373 "#      endif\n"
2374 "#    else\n"
2375 "    f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2376 "#    endif\n"
2377 "\n"
2378 "#  endif\n"
2379 "#  ifdef USESHADOWMAPORTHO\n"
2380 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2381 "#  else\n"
2382 "       return f;\n"
2383 "#  endif\n"
2384 "}\n"
2385 "# endif\n"
2386 "\n"
2387 "# ifdef USESHADOWMAP2D\n"
2388 "#ifdef USESHADOWMAPVSDCT\n"
2389 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2390 "#else\n"
2391 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2392 "#endif\n"
2393 "{\n"
2394 "#ifdef USESHADOWMAPVSDCT\n"
2395 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2396 "#else\n"
2397 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2398 "#endif\n"
2399 "    float f;\n"
2400 "\n"
2401 "#  ifdef USESHADOWSAMPLER\n"
2402 "#    ifdef USESHADOWMAPPCF\n"
2403 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, float3(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
2404 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2405 "    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"
2406 "#    else\n"
2407 "    f = shadow2D(Texture_ShadowMap2D, float3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
2408 "#    endif\n"
2409 "#  else\n"
2410 "#    ifdef USESHADOWMAPPCF\n"
2411 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2412 "#      ifdef GL_ARB_texture_gather\n"
2413 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
2414 "#      else\n"
2415 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x,y)*ShadowMap_TextureScale)\n"
2416 "#      endif\n"
2417 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2418 "    center *= ShadowMap_TextureScale;\n"
2419 "    float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2420 "    float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2421 "    float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2422 "    float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2423 "    float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2424 "                lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2425 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2426 "#     else\n"
2427 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)  \n"
2428 "#      if USESHADOWMAPPCF > 1\n"
2429 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2430 "    center *= ShadowMap_TextureScale;\n"
2431 "    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"
2432 "    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"
2433 "    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"
2434 "    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"
2435 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2436 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2437 "#      else\n"
2438 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2439 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2440 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2441 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2442 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2443 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2444 "#      endif\n"
2445 "#     endif\n"
2446 "#    else\n"
2447 "    f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2448 "#    endif\n"
2449 "#  endif\n"
2450 "#  ifdef USESHADOWMAPORTHO\n"
2451 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2452 "#  else\n"
2453 "       return f;\n"
2454 "#  endif\n"
2455 "}\n"
2456 "# endif\n"
2457 "\n"
2458 "# ifdef USESHADOWMAPCUBE\n"
2459 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2460 "{\n"
2461 "    // apply depth texture cubemap as light filter\n"
2462 "    float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2463 "    float f;\n"
2464 "#  ifdef USESHADOWSAMPLER\n"
2465 "    f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2466 "#  else\n"
2467 "    f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2468 "#  endif\n"
2469 "    return f;\n"
2470 "}\n"
2471 "# endif\n"
2472 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2473 "#endif // FRAGMENT_SHADER\n"
2474 "\n"
2475 "\n"
2476 "\n"
2477 "\n"
2478 "#ifdef MODE_DEFERREDGEOMETRY\n"
2479 "#ifdef VERTEX_SHADER\n"
2480 "void main\n"
2481 "(\n"
2482 "float4 gl_Vertex : POSITION,\n"
2483 "uniform float4x4 ModelViewProjectionMatrix,\n"
2484 "#ifdef USEVERTEXTEXTUREBLEND\n"
2485 "float4 gl_Color : COLOR0,\n"
2486 "#endif\n"
2487 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2488 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2489 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2490 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2491 "uniform float4x4 TexMatrix,\n"
2492 "#ifdef USEVERTEXTEXTUREBLEND\n"
2493 "uniform float4x4 BackgroundTexMatrix,\n"
2494 "#endif\n"
2495 "uniform float4x4 ModelViewMatrix,\n"
2496 "#ifdef USEOFFSETMAPPING\n"
2497 "uniform float3 EyePosition,\n"
2498 "#endif\n"
2499 "out float4 gl_Position : POSITION,\n"
2500 "out float4 gl_FrontColor : COLOR,\n"
2501 "out float4 TexCoordBoth : TEXCOORD0,\n"
2502 "#ifdef USEOFFSETMAPPING\n"
2503 "out float3 EyeVector : TEXCOORD2,\n"
2504 "#endif\n"
2505 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2506 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2507 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2508 ")\n"
2509 "{\n"
2510 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2511 "#ifdef USEVERTEXTEXTUREBLEND\n"
2512 "       gl_FrontColor = gl_Color;\n"
2513 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2514 "#endif\n"
2515 "\n"
2516 "       // transform unnormalized eye direction into tangent space\n"
2517 "#ifdef USEOFFSETMAPPING\n"
2518 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2519 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2520 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2521 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2522 "#endif\n"
2523 "\n"
2524 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2525 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2526 "       VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2527 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2528 "}\n"
2529 "#endif // VERTEX_SHADER\n"
2530 "\n"
2531 "#ifdef FRAGMENT_SHADER\n"
2532 "void main\n"
2533 "(\n"
2534 "float4 TexCoordBoth : TEXCOORD0,\n"
2535 "float3 EyeVector : TEXCOORD2,\n"
2536 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2537 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2538 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2539 "uniform sampler2D Texture_Normal,\n"
2540 "#ifdef USEALPHAKILL\n"
2541 "uniform sampler2D Texture_Color,\n"
2542 "#endif\n"
2543 "uniform sampler2D Texture_Gloss,\n"
2544 "#ifdef USEVERTEXTEXTUREBLEND\n"
2545 "uniform sampler2D Texture_SecondaryNormal,\n"
2546 "uniform sampler2D Texture_SecondaryGloss,\n"
2547 "#endif\n"
2548 "#ifdef USEOFFSETMAPPING\n"
2549 "uniform float OffsetMapping_Scale,\n"
2550 "#endif\n"
2551 "uniform half SpecularPower,\n"
2552 "out float4 gl_FragColor : COLOR\n"
2553 ")\n"
2554 "{\n"
2555 "       float2 TexCoord = TexCoordBoth.xy;\n"
2556 "#ifdef USEOFFSETMAPPING\n"
2557 "       // apply offsetmapping\n"
2558 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2559 "#define TexCoord TexCoordOffset\n"
2560 "#endif\n"
2561 "\n"
2562 "#ifdef USEALPHAKILL\n"
2563 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2564 "               discard;\n"
2565 "#endif\n"
2566 "\n"
2567 "#ifdef USEVERTEXTEXTUREBLEND\n"
2568 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2569 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2570 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2571 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2572 "#endif\n"
2573 "\n"
2574 "#ifdef USEVERTEXTEXTUREBLEND\n"
2575 "       float3 surfacenormal = lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
2576 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2577 "#else\n"
2578 "       float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
2579 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2580 "#endif\n"
2581 "\n"
2582 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), 1);\n"
2583 "}\n"
2584 "#endif // FRAGMENT_SHADER\n"
2585 "#else // !MODE_DEFERREDGEOMETRY\n"
2586 "\n"
2587 "\n"
2588 "\n"
2589 "\n"
2590 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2591 "#ifdef VERTEX_SHADER\n"
2592 "void main\n"
2593 "(\n"
2594 "float4 gl_Vertex : POSITION,\n"
2595 "uniform float4x4 ModelViewProjectionMatrix,\n"
2596 "uniform float4x4 ModelViewMatrix,\n"
2597 "out float4 gl_Position : POSITION,\n"
2598 "out float4 ModelViewPosition : TEXCOORD0\n"
2599 ")\n"
2600 "{\n"
2601 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2602 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2603 "}\n"
2604 "#endif // VERTEX_SHADER\n"
2605 "\n"
2606 "#ifdef FRAGMENT_SHADER\n"
2607 "void main\n"
2608 "(\n"
2609 "float2 Pixel : WPOS,\n"
2610 "float4 ModelViewPosition : TEXCOORD0,\n"
2611 "uniform float4x4 ViewToLight,\n"
2612 "uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2613 "uniform float3 LightPosition,\n"
2614 "uniform half2 PixelToScreenTexCoord,\n"
2615 "uniform half3 DeferredColor_Ambient,\n"
2616 "uniform half3 DeferredColor_Diffuse,\n"
2617 "#ifdef USESPECULAR\n"
2618 "uniform half3 DeferredColor_Specular,\n"
2619 "uniform half SpecularPower,\n"
2620 "#endif\n"
2621 "uniform sampler2D Texture_Attenuation,\n"
2622 "uniform sampler2D Texture_ScreenDepth,\n"
2623 "uniform sampler2D Texture_ScreenNormalMap,\n"
2624 "\n"
2625 "#ifdef USECUBEFILTER\n"
2626 "uniform samplerCUBE Texture_Cube,\n"
2627 "#endif\n"
2628 "\n"
2629 "#ifdef USESHADOWMAPRECT\n"
2630 "# ifdef USESHADOWSAMPLER\n"
2631 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2632 "# else\n"
2633 "uniform samplerRECT Texture_ShadowMapRect,\n"
2634 "# endif\n"
2635 "#endif\n"
2636 "\n"
2637 "#ifdef USESHADOWMAP2D\n"
2638 "# ifdef USESHADOWSAMPLER\n"
2639 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2640 "# else\n"
2641 "uniform sampler2D Texture_ShadowMap2D,\n"
2642 "# endif\n"
2643 "#endif\n"
2644 "\n"
2645 "#ifdef USESHADOWMAPVSDCT\n"
2646 "uniform samplerCUBE Texture_CubeProjection,\n"
2647 "#endif\n"
2648 "\n"
2649 "#ifdef USESHADOWMAPCUBE\n"
2650 "# ifdef USESHADOWSAMPLER\n"
2651 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2652 "# else\n"
2653 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2654 "# endif\n"
2655 "#endif\n"
2656 "\n"
2657 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2658 "uniform float2 ShadowMap_TextureScale,\n"
2659 "uniform float4 ShadowMap_Parameters,\n"
2660 "#endif\n"
2661 "\n"
2662 "out float4 gl_FragData0 : COLOR0,\n"
2663 "out float4 gl_FragData1 : COLOR1\n"
2664 ")\n"
2665 "{\n"
2666 "       // calculate viewspace pixel position\n"
2667 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2668 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2669 "       float3 position;\n"
2670 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2671 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2672 "       // decode viewspace pixel normal\n"
2673 "       half4 normalmap = tex2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
2674 "       half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
2675 "       // surfacenormal = pixel normal in viewspace\n"
2676 "       // LightVector = pixel to light in viewspace\n"
2677 "       // CubeVector = position in lightspace\n"
2678 "       // eyevector = pixel to view in viewspace\n"
2679 "       float3 CubeVector = float3(mul(ViewToLight, float4(position,1)));\n"
2680 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2681 "#ifdef USEDIFFUSE\n"
2682 "       // calculate diffuse shading\n"
2683 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2684 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2685 "#endif\n"
2686 "#ifdef USESPECULAR\n"
2687 "       // calculate directional shading\n"
2688 "       float3 eyevector = position * -1.0;\n"
2689 "#  ifdef USEEXACTSPECULARMATH\n"
2690 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
2691 "#  else\n"
2692 "       half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
2693 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
2694 "#  endif\n"
2695 "#endif\n"
2696 "\n"
2697 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2698 "       fade *= ShadowMapCompare(CubeVector,\n"
2699 "# if defined(USESHADOWMAP2D)\n"
2700 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2701 "# endif\n"
2702 "# if defined(USESHADOWMAPRECT)\n"
2703 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2704 "# endif\n"
2705 "# if defined(USESHADOWMAPCUBE)\n"
2706 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2707 "# endif\n"
2708 "\n"
2709 "#ifdef USESHADOWMAPVSDCT\n"
2710 ", Texture_CubeProjection\n"
2711 "#endif\n"
2712 "       );\n"
2713 "#endif\n"
2714 "\n"
2715 "#ifdef USEDIFFUSE\n"
2716 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2717 "#else\n"
2718 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2719 "#endif\n"
2720 "#ifdef USESPECULAR\n"
2721 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2722 "#else\n"
2723 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2724 "#endif\n"
2725 "\n"
2726 "# ifdef USECUBEFILTER\n"
2727 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2728 "       gl_FragData0.rgb *= cubecolor;\n"
2729 "       gl_FragData1.rgb *= cubecolor;\n"
2730 "# endif\n"
2731 "}\n"
2732 "#endif // FRAGMENT_SHADER\n"
2733 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2734 "\n"
2735 "\n"
2736 "\n"
2737 "\n"
2738 "#ifdef VERTEX_SHADER\n"
2739 "void main\n"
2740 "(\n"
2741 "float4 gl_Vertex : POSITION,\n"
2742 "uniform float4x4 ModelViewProjectionMatrix,\n"
2743 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2744 "float4 gl_Color : COLOR0,\n"
2745 "#endif\n"
2746 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2747 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2748 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2749 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2750 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2751 "\n"
2752 "uniform float3 EyePosition,\n"
2753 "uniform float4x4 TexMatrix,\n"
2754 "#ifdef USEVERTEXTEXTUREBLEND\n"
2755 "uniform float4x4 BackgroundTexMatrix,\n"
2756 "#endif\n"
2757 "#ifdef MODE_LIGHTSOURCE\n"
2758 "uniform float4x4 ModelToLight,\n"
2759 "#endif\n"
2760 "#ifdef MODE_LIGHTSOURCE\n"
2761 "uniform float3 LightPosition,\n"
2762 "#endif\n"
2763 "#ifdef MODE_LIGHTDIRECTION\n"
2764 "uniform float3 LightDir,\n"
2765 "#endif\n"
2766 "uniform float4 FogPlane,\n"
2767 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2768 "uniform float3 LightPosition,\n"
2769 "#endif\n"
2770 "#ifdef USESHADOWMAPORTHO\n"
2771 "uniform float4x4 ShadowMapMatrix,\n"
2772 "#endif\n"
2773 "\n"
2774 "out float4 gl_FrontColor : COLOR,\n"
2775 "out float4 TexCoordBoth : TEXCOORD0,\n"
2776 "#ifdef USELIGHTMAP\n"
2777 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2778 "#endif\n"
2779 "#ifdef USEEYEVECTOR\n"
2780 "out float3 EyeVector : TEXCOORD2,\n"
2781 "#endif\n"
2782 "#ifdef USEREFLECTION\n"
2783 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2784 "#endif\n"
2785 "#ifdef USEFOG\n"
2786 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2787 "#endif\n"
2788 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2789 "out float3 LightVector : TEXCOORD1,\n"
2790 "#endif\n"
2791 "#ifdef MODE_LIGHTSOURCE\n"
2792 "out float3 CubeVector : TEXCOORD3,\n"
2793 "#endif\n"
2794 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2795 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2796 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2797 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2798 "#endif\n"
2799 "#ifdef USESHADOWMAPORTHO\n"
2800 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2801 "#endif\n"
2802 "out float4 gl_Position : POSITION\n"
2803 ")\n"
2804 "{\n"
2805 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2806 "       gl_FrontColor = gl_Color;\n"
2807 "#endif\n"
2808 "       // copy the surface texcoord\n"
2809 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2810 "#ifdef USEVERTEXTEXTUREBLEND\n"
2811 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2812 "#endif\n"
2813 "#ifdef USELIGHTMAP\n"
2814 "       TexCoordLightmap = float2(gl_MultiTexCoord4);\n"
2815 "#endif\n"
2816 "\n"
2817 "#ifdef MODE_LIGHTSOURCE\n"
2818 "       // transform vertex position into light attenuation/cubemap space\n"
2819 "       // (-1 to +1 across the light box)\n"
2820 "       CubeVector = float3(mul(ModelToLight, gl_Vertex));\n"
2821 "\n"
2822 "# ifdef USEDIFFUSE\n"
2823 "       // transform unnormalized light direction into tangent space\n"
2824 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2825 "       //  normalize it per pixel)\n"
2826 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2827 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2828 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2829 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2830 "# endif\n"
2831 "#endif\n"
2832 "\n"
2833 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2834 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2835 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2836 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2837 "#endif\n"
2838 "\n"
2839 "       // transform unnormalized eye direction into tangent space\n"
2840 "#ifdef USEEYEVECTOR\n"
2841 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2842 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2843 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2844 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2845 "#endif\n"
2846 "\n"
2847 "#ifdef USEFOG\n"
2848 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2849 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2850 "#endif\n"
2851 "\n"
2852 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2853 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2854 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2855 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2856 "#endif\n"
2857 "\n"
2858 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2859 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2860 "\n"
2861 "#ifdef USESHADOWMAPORTHO\n"
2862 "       ShadowMapTC = float3(mul(ShadowMapMatrix, gl_Position));\n"
2863 "#endif\n"
2864 "\n"
2865 "#ifdef USEREFLECTION\n"
2866 "       ModelViewProjectionPosition = gl_Position;\n"
2867 "#endif\n"
2868 "}\n"
2869 "#endif // VERTEX_SHADER\n"
2870 "\n"
2871 "\n"
2872 "\n"
2873 "\n"
2874 "#ifdef FRAGMENT_SHADER\n"
2875 "void main\n"
2876 "(\n"
2877 "#ifdef USEDEFERREDLIGHTMAP\n"
2878 "float2 Pixel : WPOS,\n"
2879 "#endif\n"
2880 "float4 gl_FrontColor : COLOR,\n"
2881 "float4 TexCoordBoth : TEXCOORD0,\n"
2882 "#ifdef USELIGHTMAP\n"
2883 "float2 TexCoordLightmap : TEXCOORD1,\n"
2884 "#endif\n"
2885 "#ifdef USEEYEVECTOR\n"
2886 "float3 EyeVector : TEXCOORD2,\n"
2887 "#endif\n"
2888 "#ifdef USEREFLECTION\n"
2889 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2890 "#endif\n"
2891 "#ifdef USEFOG\n"
2892 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2893 "#endif\n"
2894 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2895 "float3 LightVector : TEXCOORD1,\n"
2896 "#endif\n"
2897 "#ifdef MODE_LIGHTSOURCE\n"
2898 "float3 CubeVector : TEXCOORD3,\n"
2899 "#endif\n"
2900 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2901 "float4 ModelViewPosition : TEXCOORD0,\n"
2902 "#endif\n"
2903 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2904 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2905 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2906 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2907 "#endif\n"
2908 "#ifdef USESHADOWMAPORTHO\n"
2909 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2910 "#endif\n"
2911 "\n"
2912 "uniform sampler2D Texture_Normal,\n"
2913 "uniform sampler2D Texture_Color,\n"
2914 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2915 "uniform sampler2D Texture_Gloss,\n"
2916 "#endif\n"
2917 "#ifdef USEGLOW\n"
2918 "uniform sampler2D Texture_Glow,\n"
2919 "#endif\n"
2920 "#ifdef USEVERTEXTEXTUREBLEND\n"
2921 "uniform sampler2D Texture_SecondaryNormal,\n"
2922 "uniform sampler2D Texture_SecondaryColor,\n"
2923 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2924 "uniform sampler2D Texture_SecondaryGloss,\n"
2925 "#endif\n"
2926 "#ifdef USEGLOW\n"
2927 "uniform sampler2D Texture_SecondaryGlow,\n"
2928 "#endif\n"
2929 "#endif\n"
2930 "#ifdef USECOLORMAPPING\n"
2931 "uniform sampler2D Texture_Pants,\n"
2932 "uniform sampler2D Texture_Shirt,\n"
2933 "#endif\n"
2934 "#ifdef USEFOG\n"
2935 "uniform sampler2D Texture_FogHeightTexture,\n"
2936 "uniform sampler2D Texture_FogMask,\n"
2937 "#endif\n"
2938 "#ifdef USELIGHTMAP\n"
2939 "uniform sampler2D Texture_Lightmap,\n"
2940 "#endif\n"
2941 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2942 "uniform sampler2D Texture_Deluxemap,\n"
2943 "#endif\n"
2944 "#ifdef USEREFLECTION\n"
2945 "uniform sampler2D Texture_Reflection,\n"
2946 "#endif\n"
2947 "\n"
2948 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2949 "uniform sampler2D Texture_ScreenDepth,\n"
2950 "uniform sampler2D Texture_ScreenNormalMap,\n"
2951 "#endif\n"
2952 "#ifdef USEDEFERREDLIGHTMAP\n"
2953 "uniform sampler2D Texture_ScreenDiffuse,\n"
2954 "uniform sampler2D Texture_ScreenSpecular,\n"
2955 "#endif\n"
2956 "\n"
2957 "#ifdef USECOLORMAPPING\n"
2958 "uniform half3 Color_Pants,\n"
2959 "uniform half3 Color_Shirt,\n"
2960 "#endif\n"
2961 "#ifdef USEFOG\n"
2962 "uniform float3 FogColor,\n"
2963 "uniform float FogRangeRecip,\n"
2964 "uniform float FogPlaneViewDist,\n"
2965 "uniform float FogHeightFade,\n"
2966 "#endif\n"
2967 "\n"
2968 "#ifdef USEOFFSETMAPPING\n"
2969 "uniform float OffsetMapping_Scale,\n"
2970 "#endif\n"
2971 "\n"
2972 "#ifdef USEDEFERREDLIGHTMAP\n"
2973 "uniform half2 PixelToScreenTexCoord,\n"
2974 "uniform half3 DeferredMod_Diffuse,\n"
2975 "uniform half3 DeferredMod_Specular,\n"
2976 "#endif\n"
2977 "uniform half3 Color_Ambient,\n"
2978 "uniform half3 Color_Diffuse,\n"
2979 "uniform half3 Color_Specular,\n"
2980 "uniform half SpecularPower,\n"
2981 "#ifdef USEGLOW\n"
2982 "uniform half3 Color_Glow,\n"
2983 "#endif\n"
2984 "uniform half Alpha,\n"
2985 "#ifdef USEREFLECTION\n"
2986 "uniform float4 DistortScaleRefractReflect,\n"
2987 "uniform float4 ScreenScaleRefractReflect,\n"
2988 "uniform float4 ScreenCenterRefractReflect,\n"
2989 "uniform half4 ReflectColor,\n"
2990 "#endif\n"
2991 "#ifdef USEREFLECTCUBE\n"
2992 "uniform float4x4 ModelToReflectCube,\n"
2993 "uniform sampler2D Texture_ReflectMask,\n"
2994 "uniform samplerCUBE Texture_ReflectCube,\n"
2995 "#endif\n"
2996 "#ifdef MODE_LIGHTDIRECTION\n"
2997 "uniform half3 LightColor,\n"
2998 "#endif\n"
2999 "#ifdef MODE_LIGHTSOURCE\n"
3000 "uniform half3 LightColor,\n"
3001 "#endif\n"
3002 "\n"
3003 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3004 "uniform sampler2D Texture_Attenuation,\n"
3005 "uniform samplerCUBE Texture_Cube,\n"
3006 "#endif\n"
3007 "\n"
3008 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3009 "\n"
3010 "#ifdef USESHADOWMAPRECT\n"
3011 "# ifdef USESHADOWSAMPLER\n"
3012 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
3013 "# else\n"
3014 "uniform samplerRECT Texture_ShadowMapRect,\n"
3015 "# endif\n"
3016 "#endif\n"
3017 "\n"
3018 "#ifdef USESHADOWMAP2D\n"
3019 "# ifdef USESHADOWSAMPLER\n"
3020 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
3021 "# else\n"
3022 "uniform sampler2D Texture_ShadowMap2D,\n"
3023 "# endif\n"
3024 "#endif\n"
3025 "\n"
3026 "#ifdef USESHADOWMAPVSDCT\n"
3027 "uniform samplerCUBE Texture_CubeProjection,\n"
3028 "#endif\n"
3029 "\n"
3030 "#ifdef USESHADOWMAPCUBE\n"
3031 "# ifdef USESHADOWSAMPLER\n"
3032 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
3033 "# else\n"
3034 "uniform samplerCUBE Texture_ShadowMapCube,\n"
3035 "# endif\n"
3036 "#endif\n"
3037 "\n"
3038 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
3039 "uniform float2 ShadowMap_TextureScale,\n"
3040 "uniform float4 ShadowMap_Parameters,\n"
3041 "#endif\n"
3042 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3043 "\n"
3044 "out float4 gl_FragColor : COLOR\n"
3045 ")\n"
3046 "{\n"
3047 "       float2 TexCoord = TexCoordBoth.xy;\n"
3048 "#ifdef USEVERTEXTEXTUREBLEND\n"
3049 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
3050 "#endif\n"
3051 "#ifdef USEOFFSETMAPPING\n"
3052 "       // apply offsetmapping\n"
3053 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3054 "#define TexCoord TexCoordOffset\n"
3055 "#endif\n"
3056 "\n"
3057 "       // combine the diffuse textures (base, pants, shirt)\n"
3058 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3059 "#ifdef USEALPHAKILL\n"
3060 "       if (color.a < 0.5)\n"
3061 "               discard;\n"
3062 "#endif\n"
3063 "       color.a *= Alpha;\n"
3064 "#ifdef USECOLORMAPPING\n"
3065 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord)) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
3066 "#endif\n"
3067 "#ifdef USEVERTEXTEXTUREBLEND\n"
3068 "       float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3069 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3070 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3071 "       color.rgb = half3(lerp(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
3072 "       color.a = 1.0;\n"
3073 "       //color = lerp(half4(1, 0, 0, 1), color, terrainblend);\n"
3074 "#endif\n"
3075 "\n"
3076 "       // get the surface normal\n"
3077 "#ifdef USEVERTEXTEXTUREBLEND\n"
3078 "       half3 surfacenormal = normalize(half3(lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3079 "#else\n"
3080 "       half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
3081 "#endif\n"
3082 "\n"
3083 "       // get the material colors\n"
3084 "       half3 diffusetex = color.rgb;\n"
3085 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3086 "# ifdef USEVERTEXTEXTUREBLEND\n"
3087 "       half4 glosstex = half4(lerp(float4(tex2D(Texture_SecondaryGloss, TexCoord2)), float4(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
3088 "# else\n"
3089 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3090 "# endif\n"
3091 "#endif\n"
3092 "\n"
3093 "#ifdef USEREFLECTCUBE\n"
3094 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3095 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3096 "       float3 ReflectCubeTexCoord = float3(mul(ModelToReflectCube, float4(ModelReflectVector, 0)));\n"
3097 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord)) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord));\n"
3098 "#endif\n"
3099 "\n"
3100 "\n"
3101 "\n"
3102 "\n"
3103 "#ifdef MODE_LIGHTSOURCE\n"
3104 "       // light source\n"
3105 "#ifdef USEDIFFUSE\n"
3106 "       half3 lightnormal = half3(normalize(LightVector));\n"
3107 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3108 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3109 "#ifdef USESPECULAR\n"
3110 "#ifdef USEEXACTSPECULARMATH\n"
3111 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
3112 "#else\n"
3113 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3114 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
3115 "#endif\n"
3116 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3117 "#endif\n"
3118 "#else\n"
3119 "       color.rgb = diffusetex * Color_Ambient;\n"
3120 "#endif\n"
3121 "       color.rgb *= LightColor;\n"
3122 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
3123 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
3124 "       color.rgb *= ShadowMapCompare(CubeVector,\n"
3125 "# if defined(USESHADOWMAP2D)\n"
3126 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3127 "# endif\n"
3128 "# if defined(USESHADOWMAPRECT)\n"
3129 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3130 "# endif\n"
3131 "# if defined(USESHADOWMAPCUBE)\n"
3132 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
3133 "# endif\n"
3134 "\n"
3135 "#ifdef USESHADOWMAPVSDCT\n"
3136 ", Texture_CubeProjection\n"
3137 "#endif\n"
3138 "       );\n"
3139 "\n"
3140 "#endif\n"
3141 "# ifdef USECUBEFILTER\n"
3142 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector));\n"
3143 "# endif\n"
3144 "#endif // MODE_LIGHTSOURCE\n"
3145 "\n"
3146 "\n"
3147 "\n"
3148 "\n"
3149 "#ifdef MODE_LIGHTDIRECTION\n"
3150 "#define SHADING\n"
3151 "#ifdef USEDIFFUSE\n"
3152 "       half3 lightnormal = half3(normalize(LightVector));\n"
3153 "#endif\n"
3154 "#define lightcolor LightColor\n"
3155 "#endif // MODE_LIGHTDIRECTION\n"
3156 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3157 "#define SHADING\n"
3158 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3159 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3160 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3161 "       // convert modelspace light vector to tangentspace\n"
3162 "       half3 lightnormal;\n"
3163 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3164 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3165 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3166 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3167 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3168 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3169 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3170 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3171 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3172 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3173 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3174 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3175 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3176 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3177 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3178 "#define SHADING\n"
3179 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3180 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3181 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3182 "#endif\n"
3183 "\n"
3184 "\n"
3185 "\n"
3186 "\n"
3187 "#ifdef MODE_LIGHTMAP\n"
3188 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
3189 "#endif // MODE_LIGHTMAP\n"
3190 "#ifdef MODE_VERTEXCOLOR\n"
3191 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3192 "#endif // MODE_VERTEXCOLOR\n"
3193 "#ifdef MODE_FLATCOLOR\n"
3194 "       color.rgb = diffusetex * Color_Ambient;\n"
3195 "#endif // MODE_FLATCOLOR\n"
3196 "\n"
3197 "\n"
3198 "\n"
3199 "\n"
3200 "#ifdef SHADING\n"
3201 "# ifdef USEDIFFUSE\n"
3202 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3203 "#  ifdef USESPECULAR\n"
3204 "#   ifdef USEEXACTSPECULARMATH\n"
3205 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
3206 "#   else\n"
3207 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3208 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
3209 "#   endif\n"
3210 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3211 "#  else\n"
3212 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3213 "#  endif\n"
3214 "# else\n"
3215 "       color.rgb = diffusetex * Color_Ambient;\n"
3216 "# endif\n"
3217 "#endif\n"
3218 "\n"
3219 "#ifdef USESHADOWMAPORTHO\n"
3220 "       color.rgb *= ShadowMapCompare(ShadowMapTC,\n"
3221 "# if defined(USESHADOWMAP2D)\n"
3222 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3223 "# endif\n"
3224 "# if defined(USESHADOWMAPRECT)\n"
3225 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3226 "# endif\n"
3227 "       );\n"
3228 "#endif\n"
3229 "\n"
3230 "#ifdef USEDEFERREDLIGHTMAP\n"
3231 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3232 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
3233 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
3234 "#endif\n"
3235 "\n"
3236 "#ifdef USEGLOW\n"
3237 "#ifdef USEVERTEXTEXTUREBLEND\n"
3238 "       color.rgb += lerp(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
3239 "#else\n"
3240 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
3241 "#endif\n"
3242 "#endif\n"
3243 "\n"
3244 "#ifdef USEFOG\n"
3245 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3246 "#endif\n"
3247 "\n"
3248 "       // 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"
3249 "#ifdef USEREFLECTION\n"
3250 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3251 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3252 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3253 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
3254 "       // FIXME temporary hack to detect the case that the reflection\n"
3255 "       // gets blackened at edges due to leaving the area that contains actual\n"
3256 "       // content.\n"
3257 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3258 "       // 'appening.\n"
3259 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3260 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3261 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3262 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3263 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3264 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
3265 "#endif\n"
3266 "\n"
3267 "       gl_FragColor = float4(color);\n"
3268 "}\n"
3269 "#endif // FRAGMENT_SHADER\n"
3270 "\n"
3271 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3272 "#endif // !MODE_DEFERREDGEOMETRY\n"
3273 "#endif // !MODE_WATER\n"
3274 "#endif // !MODE_REFRACTION\n"
3275 "#endif // !MODE_BLOOMBLUR\n"
3276 "#endif // !MODE_GENERIC\n"
3277 "#endif // !MODE_POSTPROCESS\n"
3278 "#endif // !MODE_SHOWDEPTH\n"
3279 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3280 ;
3281
3282 char *glslshaderstring = NULL;
3283 char *cgshaderstring = NULL;
3284
3285 //=======================================================================================================================================================
3286
3287 typedef struct shaderpermutationinfo_s
3288 {
3289         const char *pretext;
3290         const char *name;
3291 }
3292 shaderpermutationinfo_t;
3293
3294 typedef struct shadermodeinfo_s
3295 {
3296         const char *vertexfilename;
3297         const char *geometryfilename;
3298         const char *fragmentfilename;
3299         const char *pretext;
3300         const char *name;
3301 }
3302 shadermodeinfo_t;
3303
3304 typedef enum shaderpermutation_e
3305 {
3306         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3307         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3308         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3309         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3310         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3311         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3312         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3313         SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3314         SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3315         SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3316         SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3317         SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3318         SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3319         SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3320         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<14, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3321         SHADERPERMUTATION_REFLECTION = 1<<15, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3322         SHADERPERMUTATION_OFFSETMAPPING = 1<<16, ///< adjust texcoords to roughly simulate a displacement mapped surface
3323         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<17, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3324         SHADERPERMUTATION_SHADOWMAPRECT = 1<<18, ///< (lightsource) use shadowmap rectangle texture as light filter
3325         SHADERPERMUTATION_SHADOWMAPCUBE = 1<<19, ///< (lightsource) use shadowmap cubemap texture as light filter
3326         SHADERPERMUTATION_SHADOWMAP2D = 1<<20, ///< (lightsource) use shadowmap rectangle texture as light filter
3327         SHADERPERMUTATION_SHADOWMAPPCF = 1<<21, ///< (lightsource) use percentage closer filtering on shadowmap test results
3328         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<22, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3329         SHADERPERMUTATION_SHADOWSAMPLER = 1<<23, ///< (lightsource) use hardware shadowmap test
3330         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<24, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3331         SHADERPERMUTATION_SHADOWMAPORTHO = 1<<25, //< (lightsource) use orthographic shadowmap projection
3332         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<26, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3333         SHADERPERMUTATION_ALPHAKILL = 1<<27, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3334         SHADERPERMUTATION_REFLECTCUBE = 1<<28, ///< fake reflections using global cubemap (not HDRI light probe)
3335         SHADERPERMUTATION_LIMIT = 1<<29, ///< size of permutations array
3336         SHADERPERMUTATION_COUNT = 29 ///< size of shaderpermutationinfo array
3337 }
3338 shaderpermutation_t;
3339
3340 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3341 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3342 {
3343         {"#define USEDIFFUSE\n", " diffuse"},
3344         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3345         {"#define USEVIEWTINT\n", " viewtint"},
3346         {"#define USECOLORMAPPING\n", " colormapping"},
3347         {"#define USESATURATION\n", " saturation"},
3348         {"#define USEFOGINSIDE\n", " foginside"},
3349         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3350         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3351         {"#define USEGAMMARAMPS\n", " gammaramps"},
3352         {"#define USECUBEFILTER\n", " cubefilter"},
3353         {"#define USEGLOW\n", " glow"},
3354         {"#define USEBLOOM\n", " bloom"},
3355         {"#define USESPECULAR\n", " specular"},
3356         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3357         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3358         {"#define USEREFLECTION\n", " reflection"},
3359         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3360         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3361         {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3362         {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3363         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3364         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3365         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3366         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3367         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3368         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3369         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3370         {"#define USEALPHAKILL\n", " alphakill"},
3371         {"#define USEREFLECTCUBE\n", " reflectcube"},
3372 };
3373
3374 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3375 typedef enum shadermode_e
3376 {
3377         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3378         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3379         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3380         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3381         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3382         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3383         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3384         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3385         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3386         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3387         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3388         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3389         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3390         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3391         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3392         SHADERMODE_COUNT
3393 }
3394 shadermode_t;
3395
3396 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3397 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3398 {
3399         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3400         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3401         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3402         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3403         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3404         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3405         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3406         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3407         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3408         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3409         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3410         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3411         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3412         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3413         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3414 };
3415
3416 #ifdef SUPPORTCG
3417 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3418 {
3419         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3420         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3421         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3422         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3423         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3424         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3425         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3426         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3427         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3428         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3429         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3430         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3431         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3432         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3433         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3434 };
3435 #endif
3436
3437 struct r_glsl_permutation_s;
3438 typedef struct r_glsl_permutation_s
3439 {
3440         /// hash lookup data
3441         struct r_glsl_permutation_s *hashnext;
3442         unsigned int mode;
3443         unsigned int permutation;
3444
3445         /// indicates if we have tried compiling this permutation already
3446         qboolean compiled;
3447         /// 0 if compilation failed
3448         int program;
3449         /// locations of detected uniforms in program object, or -1 if not found
3450         int loc_Texture_First;
3451         int loc_Texture_Second;
3452         int loc_Texture_GammaRamps;
3453         int loc_Texture_Normal;
3454         int loc_Texture_Color;
3455         int loc_Texture_Gloss;
3456         int loc_Texture_Glow;
3457         int loc_Texture_SecondaryNormal;
3458         int loc_Texture_SecondaryColor;
3459         int loc_Texture_SecondaryGloss;
3460         int loc_Texture_SecondaryGlow;
3461         int loc_Texture_Pants;
3462         int loc_Texture_Shirt;
3463         int loc_Texture_FogHeightTexture;
3464         int loc_Texture_FogMask;
3465         int loc_Texture_Lightmap;
3466         int loc_Texture_Deluxemap;
3467         int loc_Texture_Attenuation;
3468         int loc_Texture_Cube;
3469         int loc_Texture_Refraction;
3470         int loc_Texture_Reflection;
3471         int loc_Texture_ShadowMapRect;
3472         int loc_Texture_ShadowMapCube;
3473         int loc_Texture_ShadowMap2D;
3474         int loc_Texture_CubeProjection;
3475         int loc_Texture_ScreenDepth;
3476         int loc_Texture_ScreenNormalMap;
3477         int loc_Texture_ScreenDiffuse;
3478         int loc_Texture_ScreenSpecular;
3479         int loc_Texture_ReflectMask;
3480         int loc_Texture_ReflectCube;
3481         int loc_Alpha;
3482         int loc_BloomBlur_Parameters;
3483         int loc_ClientTime;
3484         int loc_Color_Ambient;
3485         int loc_Color_Diffuse;
3486         int loc_Color_Specular;
3487         int loc_Color_Glow;
3488         int loc_Color_Pants;
3489         int loc_Color_Shirt;
3490         int loc_DeferredColor_Ambient;
3491         int loc_DeferredColor_Diffuse;
3492         int loc_DeferredColor_Specular;
3493         int loc_DeferredMod_Diffuse;
3494         int loc_DeferredMod_Specular;
3495         int loc_DistortScaleRefractReflect;
3496         int loc_EyePosition;
3497         int loc_FogColor;
3498         int loc_FogHeightFade;
3499         int loc_FogPlane;
3500         int loc_FogPlaneViewDist;
3501         int loc_FogRangeRecip;
3502         int loc_LightColor;
3503         int loc_LightDir;
3504         int loc_LightPosition;
3505         int loc_OffsetMapping_Scale;
3506         int loc_PixelSize;
3507         int loc_ReflectColor;
3508         int loc_ReflectFactor;
3509         int loc_ReflectOffset;
3510         int loc_RefractColor;
3511         int loc_Saturation;
3512         int loc_ScreenCenterRefractReflect;
3513         int loc_ScreenScaleRefractReflect;
3514         int loc_ScreenToDepth;
3515         int loc_ShadowMap_Parameters;
3516         int loc_ShadowMap_TextureScale;
3517         int loc_SpecularPower;
3518         int loc_UserVec1;
3519         int loc_UserVec2;
3520         int loc_UserVec3;
3521         int loc_UserVec4;
3522         int loc_ViewTintColor;
3523         int loc_ViewToLight;
3524         int loc_ModelToLight;
3525         int loc_TexMatrix;
3526         int loc_BackgroundTexMatrix;
3527         int loc_ModelViewProjectionMatrix;
3528         int loc_ModelViewMatrix;
3529         int loc_PixelToScreenTexCoord;
3530         int loc_ModelToReflectCube;
3531         int loc_ShadowMapMatrix;        
3532 }
3533 r_glsl_permutation_t;
3534
3535 #define SHADERPERMUTATION_HASHSIZE 256
3536
3537 /// information about each possible shader permutation
3538 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3539 /// currently selected permutation
3540 r_glsl_permutation_t *r_glsl_permutation;
3541 /// storage for permutations linked in the hash table
3542 memexpandablearray_t r_glsl_permutationarray;
3543
3544 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3545 {
3546         //unsigned int hashdepth = 0;
3547         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3548         r_glsl_permutation_t *p;
3549         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3550         {
3551                 if (p->mode == mode && p->permutation == permutation)
3552                 {
3553                         //if (hashdepth > 10)
3554                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3555                         return p;
3556                 }
3557                 //hashdepth++;
3558         }
3559         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3560         p->mode = mode;
3561         p->permutation = permutation;
3562         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3563         r_glsl_permutationhash[mode][hashindex] = p;
3564         //if (hashdepth > 10)
3565         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3566         return p;
3567 }
3568
3569 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3570 {
3571         char *shaderstring;
3572         if (!filename || !filename[0])
3573                 return NULL;
3574         if (!strcmp(filename, "glsl/default.glsl"))
3575         {
3576                 if (!glslshaderstring)
3577                 {
3578                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3579                         if (glslshaderstring)
3580                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3581                         else
3582                                 glslshaderstring = (char *)builtinshaderstring;
3583                 }
3584                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3585                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3586                 return shaderstring;
3587         }
3588         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3589         if (shaderstring)
3590         {
3591                 if (printfromdisknotice)
3592                         Con_DPrintf("from disk %s... ", filename);
3593                 return shaderstring;
3594         }
3595         return shaderstring;
3596 }
3597
3598 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3599 {
3600         int i;
3601         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3602         int vertstrings_count = 0;
3603         int geomstrings_count = 0;
3604         int fragstrings_count = 0;
3605         char *vertexstring, *geometrystring, *fragmentstring;
3606         const char *vertstrings_list[32+3];
3607         const char *geomstrings_list[32+3];
3608         const char *fragstrings_list[32+3];
3609         char permutationname[256];
3610
3611         if (p->compiled)
3612                 return;
3613         p->compiled = true;
3614         p->program = 0;
3615
3616         permutationname[0] = 0;
3617         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3618         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3619         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3620
3621         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3622
3623         // the first pretext is which type of shader to compile as
3624         // (later these will all be bound together as a program object)
3625         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3626         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3627         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3628
3629         // the second pretext is the mode (for example a light source)
3630         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3631         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3632         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3633         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3634
3635         // now add all the permutation pretexts
3636         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3637         {
3638                 if (permutation & (1<<i))
3639                 {
3640                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3641                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3642                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3643                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3644                 }
3645                 else
3646                 {
3647                         // keep line numbers correct
3648                         vertstrings_list[vertstrings_count++] = "\n";
3649                         geomstrings_list[geomstrings_count++] = "\n";
3650                         fragstrings_list[fragstrings_count++] = "\n";
3651                 }
3652         }
3653
3654         // now append the shader text itself
3655         vertstrings_list[vertstrings_count++] = vertexstring;
3656         geomstrings_list[geomstrings_count++] = geometrystring;
3657         fragstrings_list[fragstrings_count++] = fragmentstring;
3658
3659         // if any sources were NULL, clear the respective list
3660         if (!vertexstring)
3661                 vertstrings_count = 0;
3662         if (!geometrystring)
3663                 geomstrings_count = 0;
3664         if (!fragmentstring)
3665                 fragstrings_count = 0;
3666
3667         // compile the shader program
3668         if (vertstrings_count + geomstrings_count + fragstrings_count)
3669                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3670         if (p->program)
3671         {
3672                 CHECKGLERROR
3673                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3674                 // look up all the uniform variable names we care about, so we don't
3675                 // have to look them up every time we set them
3676
3677                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3678                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3679                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3680                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3681                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3682                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3683                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3684                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3685                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3686                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3687                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3688                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3689                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3690                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3691                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3692                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3693                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3694                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3695                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3696                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3697                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3698                 p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3699                 p->loc_Texture_ShadowMapCube      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3700                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3701                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3702                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3703                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3704                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3705                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3706                 p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3707                 p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3708                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3709                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3710                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3711                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3712                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3713                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3714                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3715                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3716                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3717                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3718                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3719                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3720                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3721                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3722                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3723                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3724                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3725                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3726                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3727                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3728                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3729                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3730                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3731                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3732                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3733                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3734                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3735                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3736                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3737                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3738                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3739                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3740                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3741                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3742                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3743                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3744                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3745                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3746                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3747                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3748                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3749                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3750                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3751                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3752                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3753                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3754                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3755                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3756                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3757                 p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3758                 p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");            
3759                 // initialize the samplers to refer to the texture units we use
3760                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3761                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3762                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3763                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3764                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3765                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3766                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3767                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3768                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3769                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3770                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3771                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3772                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3773                 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3774                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3775                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3776                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3777                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3778                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3779                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3780                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3781                 if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT);
3782                 if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
3783                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D);
3784                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3785                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3786                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3787                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3788                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3789                 if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
3790                 if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
3791                 CHECKGLERROR
3792                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3793         }
3794         else
3795                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3796
3797         // free the strings
3798         if (vertexstring)
3799                 Mem_Free(vertexstring);
3800         if (geometrystring)
3801                 Mem_Free(geometrystring);
3802         if (fragmentstring)
3803                 Mem_Free(fragmentstring);
3804 }
3805
3806 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3807 {
3808         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3809         if (r_glsl_permutation != perm)
3810         {
3811                 r_glsl_permutation = perm;
3812                 if (!r_glsl_permutation->program)
3813                 {
3814                         if (!r_glsl_permutation->compiled)
3815                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3816                         if (!r_glsl_permutation->program)
3817                         {
3818                                 // remove features until we find a valid permutation
3819                                 int i;
3820                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3821                                 {
3822                                         // reduce i more quickly whenever it would not remove any bits
3823                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3824                                         if (!(permutation & j))
3825                                                 continue;
3826                                         permutation -= j;
3827                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3828                                         if (!r_glsl_permutation->compiled)
3829                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3830                                         if (r_glsl_permutation->program)
3831                                                 break;
3832                                 }
3833                                 if (i >= SHADERPERMUTATION_COUNT)
3834                                 {
3835                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3836                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3837                                         qglUseProgramObjectARB(0);CHECKGLERROR
3838                                         return; // no bit left to clear, entire mode is broken
3839                                 }
3840                         }
3841                 }
3842                 CHECKGLERROR
3843                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3844         }
3845         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3846         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3847         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3848 }
3849
3850 #ifdef SUPPORTCG
3851 #include <Cg/cgGL.h>
3852 struct r_cg_permutation_s;
3853 typedef struct r_cg_permutation_s
3854 {
3855         /// hash lookup data
3856         struct r_cg_permutation_s *hashnext;
3857         unsigned int mode;
3858         unsigned int permutation;
3859
3860         /// indicates if we have tried compiling this permutation already
3861         qboolean compiled;
3862         /// 0 if compilation failed
3863         CGprogram vprogram;
3864         CGprogram fprogram;
3865         /// locations of detected parameters in programs, or NULL if not found
3866         CGparameter vp_EyePosition;
3867         CGparameter vp_FogPlane;
3868         CGparameter vp_LightDir;
3869         CGparameter vp_LightPosition;
3870         CGparameter vp_ModelToLight;
3871         CGparameter vp_TexMatrix;
3872         CGparameter vp_BackgroundTexMatrix;
3873         CGparameter vp_ModelViewProjectionMatrix;
3874         CGparameter vp_ModelViewMatrix;
3875         CGparameter vp_ShadowMapMatrix;
3876
3877         CGparameter fp_Texture_First;
3878         CGparameter fp_Texture_Second;
3879         CGparameter fp_Texture_GammaRamps;
3880         CGparameter fp_Texture_Normal;
3881         CGparameter fp_Texture_Color;
3882         CGparameter fp_Texture_Gloss;
3883         CGparameter fp_Texture_Glow;
3884         CGparameter fp_Texture_SecondaryNormal;
3885         CGparameter fp_Texture_SecondaryColor;
3886         CGparameter fp_Texture_SecondaryGloss;
3887         CGparameter fp_Texture_SecondaryGlow;
3888         CGparameter fp_Texture_Pants;
3889         CGparameter fp_Texture_Shirt;
3890         CGparameter fp_Texture_FogHeightTexture;
3891         CGparameter fp_Texture_FogMask;
3892         CGparameter fp_Texture_Lightmap;
3893         CGparameter fp_Texture_Deluxemap;
3894         CGparameter fp_Texture_Attenuation;
3895         CGparameter fp_Texture_Cube;
3896         CGparameter fp_Texture_Refraction;
3897         CGparameter fp_Texture_Reflection;
3898         CGparameter fp_Texture_ShadowMapRect;
3899         CGparameter fp_Texture_ShadowMapCube;
3900         CGparameter fp_Texture_ShadowMap2D;
3901         CGparameter fp_Texture_CubeProjection;
3902         CGparameter fp_Texture_ScreenDepth;
3903         CGparameter fp_Texture_ScreenNormalMap;
3904         CGparameter fp_Texture_ScreenDiffuse;
3905         CGparameter fp_Texture_ScreenSpecular;
3906         CGparameter fp_Texture_ReflectMask;
3907         CGparameter fp_Texture_ReflectCube;
3908         CGparameter fp_Alpha;
3909         CGparameter fp_BloomBlur_Parameters;
3910         CGparameter fp_ClientTime;
3911         CGparameter fp_Color_Ambient;
3912         CGparameter fp_Color_Diffuse;
3913         CGparameter fp_Color_Specular;
3914         CGparameter fp_Color_Glow;
3915         CGparameter fp_Color_Pants;
3916         CGparameter fp_Color_Shirt;
3917         CGparameter fp_DeferredColor_Ambient;
3918         CGparameter fp_DeferredColor_Diffuse;
3919         CGparameter fp_DeferredColor_Specular;
3920         CGparameter fp_DeferredMod_Diffuse;
3921         CGparameter fp_DeferredMod_Specular;
3922         CGparameter fp_DistortScaleRefractReflect;
3923         CGparameter fp_EyePosition;
3924         CGparameter fp_FogColor;
3925         CGparameter fp_FogHeightFade;
3926         CGparameter fp_FogPlane;
3927         CGparameter fp_FogPlaneViewDist;
3928         CGparameter fp_FogRangeRecip;
3929         CGparameter fp_LightColor;
3930         CGparameter fp_LightDir;
3931         CGparameter fp_LightPosition;
3932         CGparameter fp_OffsetMapping_Scale;
3933         CGparameter fp_PixelSize;
3934         CGparameter fp_ReflectColor;
3935         CGparameter fp_ReflectFactor;
3936         CGparameter fp_ReflectOffset;
3937         CGparameter fp_RefractColor;
3938         CGparameter fp_Saturation;
3939         CGparameter fp_ScreenCenterRefractReflect;
3940         CGparameter fp_ScreenScaleRefractReflect;
3941         CGparameter fp_ScreenToDepth;
3942         CGparameter fp_ShadowMap_Parameters;
3943         CGparameter fp_ShadowMap_TextureScale;
3944         CGparameter fp_SpecularPower;
3945         CGparameter fp_UserVec1;
3946         CGparameter fp_UserVec2;
3947         CGparameter fp_UserVec3;
3948         CGparameter fp_UserVec4;
3949         CGparameter fp_ViewTintColor;
3950         CGparameter fp_ViewToLight;
3951         CGparameter fp_PixelToScreenTexCoord;
3952         CGparameter fp_ModelToReflectCube;
3953 }
3954 r_cg_permutation_t;
3955
3956 /// information about each possible shader permutation
3957 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3958 /// currently selected permutation
3959 r_cg_permutation_t *r_cg_permutation;
3960 /// storage for permutations linked in the hash table
3961 memexpandablearray_t r_cg_permutationarray;
3962
3963 #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));}}
3964
3965 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3966 {
3967         //unsigned int hashdepth = 0;
3968         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3969         r_cg_permutation_t *p;
3970         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3971         {
3972                 if (p->mode == mode && p->permutation == permutation)
3973                 {
3974                         //if (hashdepth > 10)
3975                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3976                         return p;
3977                 }
3978                 //hashdepth++;
3979         }
3980         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3981         p->mode = mode;
3982         p->permutation = permutation;
3983         p->hashnext = r_cg_permutationhash[mode][hashindex];
3984         r_cg_permutationhash[mode][hashindex] = p;
3985         //if (hashdepth > 10)
3986         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3987         return p;
3988 }
3989
3990 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3991 {
3992         char *shaderstring;
3993         if (!filename || !filename[0])
3994                 return NULL;
3995         if (!strcmp(filename, "cg/default.cg"))
3996         {
3997                 if (!cgshaderstring)
3998                 {
3999                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4000                         if (cgshaderstring)
4001                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4002                         else
4003                                 cgshaderstring = (char *)builtincgshaderstring;
4004                 }
4005                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4006                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4007                 return shaderstring;
4008         }
4009         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4010         if (shaderstring)
4011         {
4012                 if (printfromdisknotice)
4013                         Con_DPrintf("from disk %s... ", filename);
4014                 return shaderstring;
4015         }
4016         return shaderstring;
4017 }
4018
4019 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4020 {
4021         // TODO: load or create .fp and .vp shader files
4022 }
4023
4024 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4025 {
4026         int i;
4027         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4028         int vertstrings_count = 0, vertstring_length = 0;
4029         int geomstrings_count = 0, geomstring_length = 0;
4030         int fragstrings_count = 0, fragstring_length = 0;
4031         char *t;
4032         char *vertexstring, *geometrystring, *fragmentstring;
4033         char *vertstring, *geomstring, *fragstring;
4034         const char *vertstrings_list[32+3];
4035         const char *geomstrings_list[32+3];
4036         const char *fragstrings_list[32+3];
4037         char permutationname[256];
4038         char cachename[256];
4039         CGprofile vertexProfile;
4040         CGprofile fragmentProfile;
4041
4042         if (p->compiled)
4043                 return;
4044         p->compiled = true;
4045         p->vprogram = NULL;
4046         p->fprogram = NULL;
4047
4048         permutationname[0] = 0;
4049         cachename[0] = 0;
4050         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
4051         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4052         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4053
4054         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4055         strlcat(cachename, "cg/", sizeof(cachename));
4056
4057         // the first pretext is which type of shader to compile as
4058         // (later these will all be bound together as a program object)
4059         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4060         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4061         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4062
4063         // the second pretext is the mode (for example a light source)
4064         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4065         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4066         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4067         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4068         strlcat(cachename, modeinfo->name, sizeof(cachename));
4069
4070         // now add all the permutation pretexts
4071         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4072         {
4073                 if (permutation & (1<<i))
4074                 {
4075                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4076                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4077                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4078                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4079                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4080                 }
4081                 else
4082                 {
4083                         // keep line numbers correct
4084                         vertstrings_list[vertstrings_count++] = "\n";
4085                         geomstrings_list[geomstrings_count++] = "\n";
4086                         fragstrings_list[fragstrings_count++] = "\n";
4087                 }
4088         }
4089
4090         // replace spaces in the cachename with _ characters
4091         for (i = 0;cachename[i];i++)
4092                 if (cachename[i] == ' ')
4093                         cachename[i] = '_';
4094
4095         // now append the shader text itself
4096         vertstrings_list[vertstrings_count++] = vertexstring;
4097         geomstrings_list[geomstrings_count++] = geometrystring;
4098         fragstrings_list[fragstrings_count++] = fragmentstring;
4099
4100         // if any sources were NULL, clear the respective list
4101         if (!vertexstring)
4102                 vertstrings_count = 0;
4103         if (!geometrystring)
4104                 geomstrings_count = 0;
4105         if (!fragmentstring)
4106                 fragstrings_count = 0;
4107
4108         vertstring_length = 0;
4109         for (i = 0;i < vertstrings_count;i++)
4110                 vertstring_length += strlen(vertstrings_list[i]);
4111         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4112         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4113                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4114
4115         geomstring_length = 0;
4116         for (i = 0;i < geomstrings_count;i++)
4117                 geomstring_length += strlen(geomstrings_list[i]);
4118         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4119         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4120                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4121
4122         fragstring_length = 0;
4123         for (i = 0;i < fragstrings_count;i++)
4124                 fragstring_length += strlen(fragstrings_list[i]);
4125         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4126         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4127                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4128
4129         CHECKGLERROR
4130         CHECKCGERROR
4131         //vertexProfile = CG_PROFILE_ARBVP1;
4132         //fragmentProfile = CG_PROFILE_ARBFP1;
4133         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4134         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4135         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4136         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4137         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4138         CHECKGLERROR
4139
4140         // try to load the cached shader, or generate one
4141         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4142
4143         // if caching failed, do a dynamic compile for now
4144         CHECKCGERROR
4145         if (vertstring[0] && !p->vprogram)
4146                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4147         CHECKCGERROR
4148         if (fragstring[0] && !p->fprogram)
4149                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4150         CHECKCGERROR
4151
4152         // look up all the uniform variable names we care about, so we don't
4153         // have to look them up every time we set them
4154         if (p->vprogram)
4155         {
4156                 CHECKCGERROR
4157                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4158                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4159                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4160                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4161                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4162                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4163                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4164                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4165                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4166                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4167                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4168                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4169                 CHECKCGERROR
4170         }
4171         if (p->fprogram)
4172         {
4173                 CHECKCGERROR
4174                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4175                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4176                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4177                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4178                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4179                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4180                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4181                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4182                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4183                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4184                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4185                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4186                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4187                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4188                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4189                 p->fp_Texture_FogHeightTexture   = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4190                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4191                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4192                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4193                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4194                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4195                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4196                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4197                 p->fp_Texture_ShadowMapRect      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
4198                 p->fp_Texture_ShadowMapCube      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
4199                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4200                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4201                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4202                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4203                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4204                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4205                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4206                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4207                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4208                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4209                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4210                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4211                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4212                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4213                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4214                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4215                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4216                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4217                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4218                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4219                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4220                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4221                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4222                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4223                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4224                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4225                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4226                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4227                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4228                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4229                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4230                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4231                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4232                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4233                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4234                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4235                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4236                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4237                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4238                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4239                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4240                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4241                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4242                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4243                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4244                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4245                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4246                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4247                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4248                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4249                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4250                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4251                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4252                 CHECKCGERROR
4253         }
4254
4255         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4256                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4257         else
4258                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4259
4260         // free the strings
4261         if (vertstring)
4262                 Mem_Free(vertstring);
4263         if (geomstring)
4264                 Mem_Free(geomstring);
4265         if (fragstring)
4266                 Mem_Free(fragstring);
4267         if (vertexstring)
4268                 Mem_Free(vertexstring);
4269         if (geometrystring)
4270                 Mem_Free(geometrystring);
4271         if (fragmentstring)
4272                 Mem_Free(fragmentstring);
4273 }
4274
4275 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4276 {
4277         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4278         CHECKGLERROR
4279         CHECKCGERROR
4280         if (r_cg_permutation != perm)
4281         {
4282                 r_cg_permutation = perm;
4283                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4284                 {
4285                         if (!r_cg_permutation->compiled)
4286                                 R_CG_CompilePermutation(perm, mode, permutation);
4287                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4288                         {
4289                                 // remove features until we find a valid permutation
4290                                 int i;
4291                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4292                                 {
4293                                         // reduce i more quickly whenever it would not remove any bits
4294                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4295                                         if (!(permutation & j))
4296                                                 continue;
4297                                         permutation -= j;
4298                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4299                                         if (!r_cg_permutation->compiled)
4300                                                 R_CG_CompilePermutation(perm, mode, permutation);
4301                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4302                                                 break;
4303                                 }
4304                                 if (i >= SHADERPERMUTATION_COUNT)
4305                                 {
4306                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4307                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4308                                         return; // no bit left to clear, entire mode is broken
4309                                 }
4310                         }
4311                 }
4312                 CHECKGLERROR
4313                 CHECKCGERROR
4314                 if (r_cg_permutation->vprogram)
4315                 {
4316                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4317                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4318                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4319                 }
4320                 else
4321                 {
4322                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4323                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4324                 }
4325                 if (r_cg_permutation->fprogram)
4326                 {
4327                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4328                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4329                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4330                 }
4331                 else
4332                 {
4333                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4334                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4335                 }
4336         }
4337         CHECKCGERROR
4338         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4339         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4340         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4341 }
4342
4343 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4344 {
4345         cgGLSetTextureParameter(param, R_GetTexture(tex));
4346         cgGLEnableTextureParameter(param);
4347 }
4348 #endif
4349
4350 void R_GLSL_Restart_f(void)
4351 {
4352         unsigned int i, limit;
4353         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4354                 Mem_Free(glslshaderstring);
4355         glslshaderstring = NULL;
4356         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4357                 Mem_Free(cgshaderstring);
4358         cgshaderstring = NULL;
4359         switch(vid.renderpath)
4360         {
4361         case RENDERPATH_GL20:
4362                 {
4363                         r_glsl_permutation_t *p;
4364                         r_glsl_permutation = NULL;
4365                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4366                         for (i = 0;i < limit;i++)
4367                         {
4368                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4369                                 {
4370                                         GL_Backend_FreeProgram(p->program);
4371                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4372                                 }
4373                         }
4374                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4375                 }
4376                 break;
4377         case RENDERPATH_CGGL:
4378 #ifdef SUPPORTCG
4379                 {
4380                         r_cg_permutation_t *p;
4381                         r_cg_permutation = NULL;
4382                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4383                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4384                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4385                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4386                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4387                         for (i = 0;i < limit;i++)
4388                         {
4389                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4390                                 {
4391                                         if (p->vprogram)
4392                                                 cgDestroyProgram(p->vprogram);
4393                                         if (p->fprogram)
4394                                                 cgDestroyProgram(p->fprogram);
4395                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4396                                 }
4397                         }
4398                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4399                 }
4400                 break;
4401 #endif
4402         case RENDERPATH_GL13:
4403         case RENDERPATH_GL11:
4404                 break;
4405         }
4406 }
4407
4408 void R_GLSL_DumpShader_f(void)
4409 {
4410         int i;
4411         qfile_t *file;
4412
4413         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4414         if (file)
4415         {
4416                 FS_Print(file, "/* The engine may define the following macros:\n");
4417                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4418                 for (i = 0;i < SHADERMODE_COUNT;i++)
4419                         FS_Print(file, glslshadermodeinfo[i].pretext);
4420                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4421                         FS_Print(file, shaderpermutationinfo[i].pretext);
4422                 FS_Print(file, "*/\n");
4423                 FS_Print(file, builtinshaderstring);
4424                 FS_Close(file);
4425                 Con_Printf("glsl/default.glsl written\n");
4426         }
4427         else
4428                 Con_Printf("failed to write to glsl/default.glsl\n");
4429
4430 #ifdef SUPPORTCG
4431         file = FS_OpenRealFile("cg/default.cg", "w", false);
4432         if (file)
4433         {
4434                 FS_Print(file, "/* The engine may define the following macros:\n");
4435                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4436                 for (i = 0;i < SHADERMODE_COUNT;i++)
4437                         FS_Print(file, cgshadermodeinfo[i].pretext);
4438                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4439                         FS_Print(file, shaderpermutationinfo[i].pretext);
4440                 FS_Print(file, "*/\n");
4441                 FS_Print(file, builtincgshaderstring);
4442                 FS_Close(file);
4443                 Con_Printf("cg/default.cg written\n");
4444         }
4445         else
4446                 Con_Printf("failed to write to cg/default.cg\n");
4447 #endif
4448 }
4449
4450 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4451 {
4452         if (!second)
4453                 texturemode = GL_MODULATE;
4454         switch (vid.renderpath)
4455         {
4456         case RENDERPATH_GL20:
4457                 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))));
4458                 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
4459                 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, second);
4460                 break;
4461         case RENDERPATH_CGGL:
4462 #ifdef SUPPORTCG
4463                 CHECKCGERROR
4464                 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))));
4465                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4466                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4467 #endif
4468                 break;
4469         case RENDERPATH_GL13:
4470                 R_Mesh_TexBind(0, first );
4471                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4472                 R_Mesh_TexBind(1, second);
4473                 if (second)
4474                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4475                 break;
4476         case RENDERPATH_GL11:
4477                 R_Mesh_TexBind(0, first );
4478                 break;
4479         }
4480 }
4481
4482 void R_SetupShader_DepthOrShadow(void)
4483 {
4484         switch (vid.renderpath)
4485         {
4486         case RENDERPATH_GL20:
4487                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4488                 break;
4489         case RENDERPATH_CGGL:
4490 #ifdef SUPPORTCG
4491                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4492 #endif
4493                 break;
4494         case RENDERPATH_GL13:
4495                 R_Mesh_TexBind(0, 0);
4496                 R_Mesh_TexBind(1, 0);
4497                 break;
4498         case RENDERPATH_GL11:
4499                 R_Mesh_TexBind(0, 0);
4500                 break;
4501         }
4502 }
4503
4504 void R_SetupShader_ShowDepth(void)
4505 {
4506         switch (vid.renderpath)
4507         {
4508         case RENDERPATH_GL20:
4509                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4510                 break;
4511         case RENDERPATH_CGGL:
4512 #ifdef SUPPORTCG
4513                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4514 #endif
4515                 break;
4516         case RENDERPATH_GL13:
4517                 break;
4518         case RENDERPATH_GL11:
4519                 break;
4520         }
4521 }
4522
4523 extern qboolean r_shadow_usingdeferredprepass;
4524 extern cvar_t r_shadow_deferred_8bitrange;
4525 extern rtexture_t *r_shadow_attenuationgradienttexture;
4526 extern rtexture_t *r_shadow_attenuation2dtexture;
4527 extern rtexture_t *r_shadow_attenuation3dtexture;
4528 extern qboolean r_shadow_usingshadowmaprect;
4529 extern qboolean r_shadow_usingshadowmapcube;
4530 extern qboolean r_shadow_usingshadowmap2d;
4531 extern qboolean r_shadow_usingshadowmaportho;
4532 extern float r_shadow_shadowmap_texturescale[2];
4533 extern float r_shadow_shadowmap_parameters[4];
4534 extern qboolean r_shadow_shadowmapvsdct;
4535 extern qboolean r_shadow_shadowmapsampler;
4536 extern int r_shadow_shadowmappcf;
4537 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4538 extern rtexture_t *r_shadow_shadowmap2dtexture;
4539 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4540 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4541 extern matrix4x4_t r_shadow_shadowmapmatrix;
4542 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4543 extern int r_shadow_prepass_width;
4544 extern int r_shadow_prepass_height;
4545 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4546 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4547 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4548 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4549 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
4550 {
4551         // select a permutation of the lighting shader appropriate to this
4552         // combination of texture, entity, light source, and fogging, only use the
4553         // minimum features necessary to avoid wasting rendering time in the
4554         // fragment shader on features that are not being used
4555         unsigned int permutation = 0;
4556         unsigned int mode = 0;
4557         float m16f[16];
4558         if (rsurfacepass == RSURFPASS_BACKGROUND)
4559         {
4560                 // distorted background
4561                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4562                         mode = SHADERMODE_WATER;
4563                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
4564                         mode = SHADERMODE_REFRACTION;
4565                 else
4566                 {
4567                         mode = SHADERMODE_GENERIC;
4568                         permutation |= SHADERPERMUTATION_DIFFUSE;
4569                 }
4570                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4571                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4572                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4573                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4574                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4575                 R_Mesh_ColorPointer(NULL, 0, 0);
4576                 GL_AlphaTest(false);
4577                 GL_BlendFunc(GL_ONE, GL_ZERO);
4578         }
4579         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4580         {
4581                 if (r_glsl_offsetmapping.integer)
4582                 {
4583                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4584                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4585                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4586                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4587                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4588                         {
4589                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4590                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4591                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4592                         }
4593                 }
4594                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4595                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4596                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4597                         permutation |= SHADERPERMUTATION_ALPHAKILL;
4598                 // normalmap (deferred prepass), may use alpha test on diffuse
4599                 mode = SHADERMODE_DEFERREDGEOMETRY;
4600                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4601                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4602                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4603                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4604                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4605                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4606                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4607                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4608                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4609                 else
4610                         R_Mesh_ColorPointer(NULL, 0, 0);
4611                 GL_AlphaTest(false);
4612                 GL_BlendFunc(GL_ONE, GL_ZERO);
4613         }
4614         else if (rsurfacepass == RSURFPASS_RTLIGHT)
4615         {
4616                 if (r_glsl_offsetmapping.integer)
4617                 {
4618                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4619                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4620                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4621                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4622                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4623                         {
4624                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4625                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4626                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4627                         }
4628                 }
4629                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4630                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4631                 // light source
4632                 mode = SHADERMODE_LIGHTSOURCE;
4633                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4634                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4635                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4636                         permutation |= SHADERPERMUTATION_CUBEFILTER;
4637                 if (diffusescale > 0)
4638                         permutation |= SHADERPERMUTATION_DIFFUSE;
4639                 if (specularscale > 0)
4640                 {
4641                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4642                         if (r_shadow_glossexact.integer)
4643                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4644                 }
4645                 if (r_refdef.fogenabled)
4646                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4647                 if (rsurface.texture->colormapping)
4648                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4649                 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4650                 {
4651                         if (r_shadow_usingshadowmaprect)
4652                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4653                         if (r_shadow_usingshadowmap2d)
4654                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4655                         if (r_shadow_usingshadowmapcube)
4656                                 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4657                         else if(r_shadow_shadowmapvsdct)
4658                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4659
4660                         if (r_shadow_shadowmapsampler)
4661                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4662                         if (r_shadow_shadowmappcf > 1)
4663                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4664                         else if (r_shadow_shadowmappcf)
4665                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4666                 }
4667                 if (rsurface.texture->reflectmasktexture)
4668                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4669                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4670                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4671                 {
4672                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4673                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4674                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4675                 }
4676                 else
4677                 {
4678                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4679                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4680                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4681                 }
4682                 //R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4683                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4684                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4685                 else
4686                         R_Mesh_ColorPointer(NULL, 0, 0);
4687                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4688                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4689         }
4690         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4691         {
4692                 if (r_glsl_offsetmapping.integer)
4693                 {
4694                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4695                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4696                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4697                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4698                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4699                         {
4700                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4701                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4702                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4703                         }
4704                 }
4705                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4706                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4707                 // unshaded geometry (fullbright or ambient model lighting)
4708                 mode = SHADERMODE_FLATCOLOR;
4709                 ambientscale = diffusescale = specularscale = 0;
4710                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4711                         permutation |= SHADERPERMUTATION_GLOW;
4712                 if (r_refdef.fogenabled)
4713                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4714                 if (rsurface.texture->colormapping)
4715                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4716                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4717                 {
4718                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4719                         if (r_shadow_usingshadowmaprect)
4720                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4721                         if (r_shadow_usingshadowmap2d)
4722                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4723
4724                         if (r_shadow_shadowmapsampler)
4725                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4726                         if (r_shadow_shadowmappcf > 1)
4727                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4728                         else if (r_shadow_shadowmappcf)
4729                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4730                 }
4731                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4732                         permutation |= SHADERPERMUTATION_REFLECTION;
4733                 if (rsurface.texture->reflectmasktexture)
4734                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4735                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4736                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4737                 {
4738                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4739                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4740                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4741                 }
4742                 else
4743                 {
4744                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4745                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4746                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4747                 }
4748                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4749                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4750                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4751                 else
4752                         R_Mesh_ColorPointer(NULL, 0, 0);
4753                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4754                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4755         }
4756         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4757         {
4758                 if (r_glsl_offsetmapping.integer)
4759                 {
4760                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4761                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4762                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4763                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4764                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4765                         {
4766                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4767                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4768                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4769                         }
4770                 }
4771                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4772                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4773                 // directional model lighting
4774                 mode = SHADERMODE_LIGHTDIRECTION;
4775                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4776                         permutation |= SHADERPERMUTATION_GLOW;
4777                 permutation |= SHADERPERMUTATION_DIFFUSE;
4778                 if (specularscale > 0)
4779                 {
4780                         permutation |= SHADERPERMUTATION_SPECULAR;
4781                         if (r_shadow_glossexact.integer)
4782                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4783                 }
4784                 if (r_refdef.fogenabled)
4785                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4786                 if (rsurface.texture->colormapping)
4787                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4788                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4789                 {
4790                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4791                         if (r_shadow_usingshadowmaprect)
4792                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4793                         if (r_shadow_usingshadowmap2d)
4794                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4795
4796                         if (r_shadow_shadowmapsampler)
4797                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4798                         if (r_shadow_shadowmappcf > 1)
4799                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4800                         else if (r_shadow_shadowmappcf)
4801                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4802                 }
4803                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4804                         permutation |= SHADERPERMUTATION_REFLECTION;
4805                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4806                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4807                 if (rsurface.texture->reflectmasktexture)
4808                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4809                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4810                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4811                 {
4812                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4813                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4814                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4815                 }
4816                 else
4817                 {
4818                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4819                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4820                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4821                 }
4822                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4823                 R_Mesh_ColorPointer(NULL, 0, 0);
4824                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4825                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4826         }
4827         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
4828         {
4829                 if (r_glsl_offsetmapping.integer)
4830                 {
4831                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4832                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4833                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4834                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4835                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4836                         {
4837                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4838                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4839                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4840                         }
4841                 }
4842                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4843                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4844                 // ambient model lighting
4845                 mode = SHADERMODE_LIGHTDIRECTION;
4846                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4847                         permutation |= SHADERPERMUTATION_GLOW;
4848                 if (r_refdef.fogenabled)
4849                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4850                 if (rsurface.texture->colormapping)
4851                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4852                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4853                 {
4854                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4855                         if (r_shadow_usingshadowmaprect)
4856                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4857                         if (r_shadow_usingshadowmap2d)
4858                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4859
4860                         if (r_shadow_shadowmapsampler)
4861                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4862                         if (r_shadow_shadowmappcf > 1)
4863                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4864                         else if (r_shadow_shadowmappcf)
4865                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4866                 }
4867                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4868                         permutation |= SHADERPERMUTATION_REFLECTION;
4869                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4870                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4871                 if (rsurface.texture->reflectmasktexture)
4872                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4873                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4874                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4875                 {
4876                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4877                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4878                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4879                 }
4880                 else
4881                 {
4882                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4883                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4884                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4885                 }
4886                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4887                 R_Mesh_ColorPointer(NULL, 0, 0);
4888                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4889                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4890         }
4891         else
4892         {
4893                 if (r_glsl_offsetmapping.integer)
4894                 {
4895                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4896                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4897                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4898                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4899                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4900                         {
4901                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4902                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4903                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4904                         }
4905                 }
4906                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4907                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4908                 // lightmapped wall
4909                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4910                         permutation |= SHADERPERMUTATION_GLOW;
4911                 if (r_refdef.fogenabled)
4912                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4913                 if (rsurface.texture->colormapping)
4914                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4915                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4916                 {
4917                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4918                         if (r_shadow_usingshadowmaprect)
4919                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4920                         if (r_shadow_usingshadowmap2d)
4921                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4922
4923                         if (r_shadow_shadowmapsampler)
4924                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4925                         if (r_shadow_shadowmappcf > 1)
4926                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4927                         else if (r_shadow_shadowmappcf)
4928                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4929                 }
4930                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4931                         permutation |= SHADERPERMUTATION_REFLECTION;
4932                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4933                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4934                 if (rsurface.texture->reflectmasktexture)
4935                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4936                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
4937                 {
4938                         // deluxemapping (light direction texture)
4939                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
4940                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
4941                         else
4942                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4943                         permutation |= SHADERPERMUTATION_DIFFUSE;
4944                         if (specularscale > 0)
4945                         {
4946                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4947                                 if (r_shadow_glossexact.integer)
4948                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4949                         }
4950                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4951                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4952                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4953                         else
4954                                 R_Mesh_ColorPointer(NULL, 0, 0);
4955                 }
4956                 else if (r_glsl_deluxemapping.integer >= 2)
4957                 {
4958                         // fake deluxemapping (uniform light direction in tangentspace)
4959                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4960                         permutation |= SHADERPERMUTATION_DIFFUSE;
4961                         if (specularscale > 0)
4962                         {
4963                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4964                                 if (r_shadow_glossexact.integer)
4965                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4966                         }
4967                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4968                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4969                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4970                         else
4971                                 R_Mesh_ColorPointer(NULL, 0, 0);
4972                 }
4973                 else if (rsurface.uselightmaptexture)
4974                 {
4975                         // ordinary lightmapping (q1bsp, q3bsp)
4976                         mode = SHADERMODE_LIGHTMAP;
4977                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4978                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4979                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4980                         else
4981                                 R_Mesh_ColorPointer(NULL, 0, 0);
4982                 }
4983                 else
4984                 {
4985                         // ordinary vertex coloring (q3bsp)
4986                         mode = SHADERMODE_VERTEXCOLOR;
4987                         R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4988                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4989                 }
4990                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4991                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4992                 {
4993                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4994                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4995                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4996                 }
4997                 else
4998                 {
4999                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
5000                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
5001                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
5002                 }
5003                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5004                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5005         }
5006         switch(vid.renderpath)
5007         {
5008         case RENDERPATH_GL20:
5009                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5010                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5011                 if (mode == SHADERMODE_LIGHTSOURCE)
5012                 {
5013                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5014                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5015                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5016                         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);
5017                         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);
5018                         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);
5019         
5020                         // additive passes are only darkened by fog, not tinted
5021                         if (r_glsl_permutation->loc_FogColor >= 0)
5022                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5023                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5024                 }
5025                 else
5026                 {
5027                         if (mode == SHADERMODE_FLATCOLOR)
5028                         {
5029                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
5030                         }
5031                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5032                         {
5033                                 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]);
5034                                 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]);
5035                                 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);
5036                                 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);
5037                                 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);
5038                                 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]);
5039                                 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]);
5040                         }
5041                         else
5042                         {
5043                                 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]);
5044                                 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]);
5045                                 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);
5046                                 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);
5047                                 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);
5048                         }
5049                         // additive passes are only darkened by fog, not tinted
5050                         if (r_glsl_permutation->loc_FogColor >= 0)
5051                         {
5052                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5053                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5054                                 else
5055                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5056                         }
5057                         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);
5058                         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]);
5059                         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]);
5060                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
5061                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
5062                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5063                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5064                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5065                 }
5066                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5067                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5068                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5069                 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]);
5070                 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]);
5071
5072                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5073                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
5074                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5075                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5076                 {
5077                         if (rsurface.texture->pantstexture)
5078                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5079                         else
5080                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5081                 }
5082                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5083                 {
5084                         if (rsurface.texture->shirttexture)
5085                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5086                         else
5087                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5088                 }
5089                 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]);
5090                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5091                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5092                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5093                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5094                 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]);
5095                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5096
5097         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
5098         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
5099         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
5100                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5101                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5102                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5103                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5104                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5105                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5106                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5107                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5108                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5109                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5110                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5111                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5112                 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5113                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5114                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_white                                     );
5115                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_blanknormalmap                            );
5116                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5117                 if (r_glsl_permutation->loc_Texture_Refraction      >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , r_texture_white                                     );
5118                 if (r_glsl_permutation->loc_Texture_Reflection      >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , r_texture_white                                     );
5119                 if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5120                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5121                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5122                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5123                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5124                 {
5125                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
5126                         if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT, r_shadow_shadowmaprectangletexture                  );
5127                         if (rsurface.rtlight)
5128                         {
5129                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5130                                 if (r_shadow_usingshadowmapcube)
5131                                         if (r_glsl_permutation->loc_Texture_ShadowMapCube   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE     , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5132                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5133                         }
5134                 }
5135                 CHECKGLERROR
5136                 break;
5137         case RENDERPATH_CGGL:
5138 #ifdef SUPPORTCG
5139                 R_SetupShader_SetPermutationCG(mode, permutation);
5140                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
5141                 if (mode == SHADERMODE_LIGHTSOURCE)
5142                 {
5143                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
5144                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5145                 }
5146                 else
5147                 {
5148                         if (mode == SHADERMODE_LIGHTDIRECTION)
5149                         {
5150                                 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
5151                         }
5152                 }
5153                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
5154                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
5155                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
5156                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5157                 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
5158                 CHECKGLERROR
5159
5160                 if (mode == SHADERMODE_LIGHTSOURCE)
5161                 {
5162                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5163                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
5164                         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
5165                         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
5166                         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
5167
5168                         // additive passes are only darkened by fog, not tinted
5169                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
5170                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5171                 }
5172                 else
5173                 {
5174                         if (mode == SHADERMODE_FLATCOLOR)
5175                         {
5176                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);CHECKCGERROR
5177                         }
5178                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5179                         {
5180                                 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
5181                                 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
5182                                 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
5183                                 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
5184                                 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
5185                                 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
5186                                 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
5187                         }
5188                         else
5189                         {
5190                                 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
5191                                 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
5192                                 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
5193                                 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
5194                                 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
5195                         }
5196                         // additive passes are only darkened by fog, not tinted
5197                         if (r_cg_permutation->fp_FogColor)
5198                         {
5199                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5200                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
5201                                 else
5202                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5203                                 CHECKCGERROR
5204                         }
5205                         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
5206                         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
5207                         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
5208                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
5209                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
5210                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
5211                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
5212                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5213                 }
5214                 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
5215                 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
5216                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
5217                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
5218                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5219                 if (r_cg_permutation->fp_Color_Pants)
5220                 {
5221                         if (rsurface.texture->pantstexture)
5222                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5223                         else
5224                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
5225                         CHECKCGERROR
5226                 }
5227                 if (r_cg_permutation->fp_Color_Shirt)
5228                 {
5229                         if (rsurface.texture->shirttexture)
5230                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5231                         else
5232                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
5233                         CHECKCGERROR
5234                 }
5235                 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
5236                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
5237                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
5238                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
5239                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
5240                 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
5241                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5242
5243         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
5244         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
5245         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
5246                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
5247                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
5248                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
5249                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
5250                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
5251                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
5252                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
5253                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
5254                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
5255                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
5256                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
5257                 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
5258                 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
5259                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
5260                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , r_texture_white                                     );CHECKCGERROR
5261                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , r_texture_blanknormalmap                            );CHECKCGERROR
5262                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
5263                 if (r_cg_permutation->fp_Texture_Refraction     ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction     , r_texture_white                                     );CHECKCGERROR
5264                 if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , r_texture_white                                     );CHECKCGERROR
5265                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
5266                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
5267                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
5268                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
5269                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5270                 {
5271                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5272                         if (r_cg_permutation->fp_Texture_ShadowMapRect  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
5273                         if (rsurface.rtlight)
5274                         {
5275                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
5276                                 if (r_shadow_usingshadowmapcube)
5277                                         if (r_cg_permutation->fp_Texture_ShadowMapCube  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5278                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
5279                         }
5280                 }
5281
5282                 CHECKGLERROR
5283 #endif
5284                 break;
5285         case RENDERPATH_GL13:
5286         case RENDERPATH_GL11:
5287                 break;
5288         }
5289 }
5290
5291 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
5292 {
5293         // select a permutation of the lighting shader appropriate to this
5294         // combination of texture, entity, light source, and fogging, only use the
5295         // minimum features necessary to avoid wasting rendering time in the
5296         // fragment shader on features that are not being used
5297         unsigned int permutation = 0;
5298         unsigned int mode = 0;
5299         const float *lightcolorbase = rtlight->currentcolor;
5300         float ambientscale = rtlight->ambientscale;
5301         float diffusescale = rtlight->diffusescale;
5302         float specularscale = rtlight->specularscale;
5303         // this is the location of the light in view space
5304         vec3_t viewlightorigin;
5305         // this transforms from view space (camera) to light space (cubemap)
5306         matrix4x4_t viewtolight;
5307         matrix4x4_t lighttoview;
5308         float viewtolight16f[16];
5309         float range = 1.0f / r_shadow_deferred_8bitrange.value;
5310         // light source
5311         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
5312         if (rtlight->currentcubemap != r_texture_whitecube)
5313                 permutation |= SHADERPERMUTATION_CUBEFILTER;
5314         if (diffusescale > 0)
5315                 permutation |= SHADERPERMUTATION_DIFFUSE;
5316         if (specularscale > 0)
5317         {
5318                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5319                 if (r_shadow_glossexact.integer)
5320                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5321         }
5322         if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
5323         {
5324                 if (r_shadow_usingshadowmaprect)
5325                         permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5326                 if (r_shadow_usingshadowmap2d)
5327                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5328                 if (r_shadow_usingshadowmapcube)
5329                         permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
5330                 else if(r_shadow_shadowmapvsdct)
5331                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5332
5333                 if (r_shadow_shadowmapsampler)
5334                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5335                 if (r_shadow_shadowmappcf > 1)
5336                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5337                 else if (r_shadow_shadowmappcf)
5338                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5339         }
5340         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
5341         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
5342         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
5343         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
5344         switch(vid.renderpath)
5345         {
5346         case RENDERPATH_GL20:
5347                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5348                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5349                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
5350                 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);
5351                 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);
5352                 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);
5353                 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]);
5354                 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]);
5355                 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));
5356                 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]);
5357                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5358
5359                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
5360                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
5361                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
5362                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
5363                 if (r_glsl_permutation->loc_Texture_ShadowMapRect     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT      , r_shadow_shadowmaprectangletexture                  );
5364                 if (r_shadow_usingshadowmapcube)
5365                         if (r_glsl_permutation->loc_Texture_ShadowMapCube     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE      , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5366                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
5367                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
5368                 break;
5369         case RENDERPATH_CGGL:
5370 #ifdef SUPPORTCG
5371                 R_SetupShader_SetPermutationCG(mode, permutation);
5372                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
5373                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
5374                 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
5375                 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
5376                 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
5377                 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
5378                 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
5379                 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
5380                 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
5381                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5382
5383                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
5384                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
5385                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
5386                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
5387                 if (r_cg_permutation->fp_Texture_ShadowMapRect    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
5388                 if (r_shadow_usingshadowmapcube)
5389                         if (r_cg_permutation->fp_Texture_ShadowMapCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5390                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5391                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
5392 #endif
5393                 break;
5394         case RENDERPATH_GL13:
5395         case RENDERPATH_GL11:
5396                 break;
5397         }
5398 }
5399
5400 #define SKINFRAME_HASH 1024
5401
5402 typedef struct
5403 {
5404         int loadsequence; // incremented each level change
5405         memexpandablearray_t array;
5406         skinframe_t *hash[SKINFRAME_HASH];
5407 }
5408 r_skinframe_t;
5409 r_skinframe_t r_skinframe;
5410
5411 void R_SkinFrame_PrepareForPurge(void)
5412 {
5413         r_skinframe.loadsequence++;
5414         // wrap it without hitting zero
5415         if (r_skinframe.loadsequence >= 200)
5416                 r_skinframe.loadsequence = 1;
5417 }
5418
5419 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5420 {
5421         if (!skinframe)
5422                 return;
5423         // mark the skinframe as used for the purging code
5424         skinframe->loadsequence = r_skinframe.loadsequence;
5425 }
5426
5427 void R_SkinFrame_Purge(void)
5428 {
5429         int i;
5430         skinframe_t *s;
5431         for (i = 0;i < SKINFRAME_HASH;i++)
5432         {
5433                 for (s = r_skinframe.hash[i];s;s = s->next)
5434                 {
5435                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5436                         {
5437                                 if (s->merged == s->base)
5438                                         s->merged = NULL;
5439                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5440                                 R_PurgeTexture(s->stain );s->stain  = NULL;
5441                                 R_PurgeTexture(s->merged);s->merged = NULL;
5442                                 R_PurgeTexture(s->base  );s->base   = NULL;
5443                                 R_PurgeTexture(s->pants );s->pants  = NULL;
5444                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
5445                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
5446                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
5447                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
5448                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
5449                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
5450                                 s->loadsequence = 0;
5451                         }
5452                 }
5453         }
5454 }
5455
5456 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5457         skinframe_t *item;
5458         char basename[MAX_QPATH];
5459
5460         Image_StripImageExtension(name, basename, sizeof(basename));
5461
5462         if( last == NULL ) {
5463                 int hashindex;
5464                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5465                 item = r_skinframe.hash[hashindex];
5466         } else {
5467                 item = last->next;
5468         }
5469
5470         // linearly search through the hash bucket
5471         for( ; item ; item = item->next ) {
5472                 if( !strcmp( item->basename, basename ) ) {
5473                         return item;
5474                 }
5475         }
5476         return NULL;
5477 }
5478
5479 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5480 {
5481         skinframe_t *item;
5482         int hashindex;
5483         char basename[MAX_QPATH];
5484
5485         Image_StripImageExtension(name, basename, sizeof(basename));
5486
5487         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5488         for (item = r_skinframe.hash[hashindex];item;item = item->next)
5489                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5490                         break;
5491
5492         if (!item) {
5493                 rtexture_t *dyntexture;
5494                 // check whether its a dynamic texture
5495                 dyntexture = CL_GetDynTexture( basename );
5496                 if (!add && !dyntexture)
5497                         return NULL;
5498                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5499                 memset(item, 0, sizeof(*item));
5500                 strlcpy(item->basename, basename, sizeof(item->basename));
5501                 item->base = dyntexture; // either NULL or dyntexture handle
5502                 item->textureflags = textureflags;
5503                 item->comparewidth = comparewidth;
5504                 item->compareheight = compareheight;
5505                 item->comparecrc = comparecrc;
5506                 item->next = r_skinframe.hash[hashindex];
5507                 r_skinframe.hash[hashindex] = item;
5508         }
5509         else if( item->base == NULL )
5510         {
5511                 rtexture_t *dyntexture;
5512                 // check whether its a dynamic texture
5513                 // 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]
5514                 dyntexture = CL_GetDynTexture( basename );
5515                 item->base = dyntexture; // either NULL or dyntexture handle
5516         }
5517
5518         R_SkinFrame_MarkUsed(item);
5519         return item;
5520 }
5521
5522 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5523         { \
5524                 unsigned long long avgcolor[5], wsum; \
5525                 int pix, comp, w; \
5526                 avgcolor[0] = 0; \
5527                 avgcolor[1] = 0; \
5528                 avgcolor[2] = 0; \
5529                 avgcolor[3] = 0; \
5530                 avgcolor[4] = 0; \
5531                 wsum = 0; \
5532                 for(pix = 0; pix < cnt; ++pix) \
5533                 { \
5534                         w = 0; \
5535                         for(comp = 0; comp < 3; ++comp) \
5536                                 w += getpixel; \
5537                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5538                         { \
5539                                 ++wsum; \
5540                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5541                                 w = getpixel; \
5542                                 for(comp = 0; comp < 3; ++comp) \
5543                                         avgcolor[comp] += getpixel * w; \
5544                                 avgcolor[3] += w; \
5545                         } \
5546                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5547                         avgcolor[4] += getpixel; \
5548                 } \
5549                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5550                         avgcolor[3] = 1; \
5551                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5552                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5553                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5554                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5555         }
5556
5557 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5558 {
5559         int j;
5560         unsigned char *pixels;
5561         unsigned char *bumppixels;
5562         unsigned char *basepixels = NULL;
5563         int basepixels_width = 0;
5564         int basepixels_height = 0;
5565         skinframe_t *skinframe;
5566         rtexture_t *ddsbase = NULL;
5567         qboolean ddshasalpha = false;
5568         float ddsavgcolor[4];
5569         char basename[MAX_QPATH];
5570
5571         if (cls.state == ca_dedicated)
5572                 return NULL;
5573
5574         // return an existing skinframe if already loaded
5575         // if loading of the first image fails, don't make a new skinframe as it
5576         // would cause all future lookups of this to be missing
5577         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5578         if (skinframe && skinframe->base)
5579                 return skinframe;
5580
5581         Image_StripImageExtension(name, basename, sizeof(basename));
5582
5583         // check for DDS texture file first
5584         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor)))
5585         {
5586                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer);
5587                 if (basepixels == NULL)
5588                         return NULL;
5589         }
5590
5591         if (developer_loading.integer)
5592                 Con_Printf("loading skin \"%s\"\n", name);
5593
5594         // we've got some pixels to store, so really allocate this new texture now
5595         if (!skinframe)
5596                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5597         skinframe->stain = NULL;
5598         skinframe->merged = NULL;
5599         skinframe->base = NULL;
5600         skinframe->pants = NULL;
5601         skinframe->shirt = NULL;
5602         skinframe->nmap = NULL;
5603         skinframe->gloss = NULL;
5604         skinframe->glow = NULL;
5605         skinframe->fog = NULL;
5606         skinframe->reflect = NULL;
5607         skinframe->hasalpha = false;
5608
5609         if (ddsbase)
5610         {
5611                 skinframe->base = ddsbase;
5612                 skinframe->hasalpha = ddshasalpha;
5613                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5614                 if (r_loadfog && skinframe->hasalpha)
5615                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5616                 //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]);
5617         }
5618         else
5619         {
5620                 basepixels_width = image_width;
5621                 basepixels_height = image_height;
5622                 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);
5623                 if (textureflags & TEXF_ALPHA)
5624                 {
5625                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5626                         {
5627                                 if (basepixels[j] < 255)
5628                                 {
5629                                         skinframe->hasalpha = true;
5630                                         break;
5631                                 }
5632                         }
5633                         if (r_loadfog && skinframe->hasalpha)
5634                         {
5635                                 // has transparent pixels
5636                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5637                                 for (j = 0;j < image_width * image_height * 4;j += 4)
5638                                 {
5639                                         pixels[j+0] = 255;
5640                                         pixels[j+1] = 255;
5641                                         pixels[j+2] = 255;
5642                                         pixels[j+3] = basepixels[j+3];
5643                                 }
5644                                 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);
5645                                 Mem_Free(pixels);
5646                         }
5647                 }
5648                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5649                 //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]);
5650                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5651                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true);
5652                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
5653                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true);
5654         }
5655
5656         if (r_loaddds)
5657         {
5658                 if (r_loadnormalmap)
5659                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5660                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL);
5661                 if (r_loadgloss)
5662                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL);
5663                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL);
5664                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL);
5665                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL);
5666         }
5667
5668         // _norm is the name used by tenebrae and has been adopted as standard
5669         if (r_loadnormalmap && skinframe->nmap == NULL)
5670         {
5671                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false)) != NULL)
5672                 {
5673                         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);
5674                         Mem_Free(pixels);
5675                         pixels = NULL;
5676                 }
5677                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false)) != NULL)
5678                 {
5679                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5680                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5681                         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);
5682                         Mem_Free(pixels);
5683                         Mem_Free(bumppixels);
5684                 }
5685                 else if (r_shadow_bumpscale_basetexture.value > 0)
5686                 {
5687                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5688                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5689                         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);
5690                         Mem_Free(pixels);
5691                 }
5692                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
5693                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true);
5694         }
5695
5696         // _luma is supported only for tenebrae compatibility
5697         // _glow is the preferred name
5698         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))))
5699         {
5700                 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);
5701                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
5702                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true);
5703                 Mem_Free(pixels);pixels = NULL;
5704         }
5705
5706         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5707         {
5708                 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);
5709                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
5710                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true);
5711                 Mem_Free(pixels);
5712                 pixels = NULL;
5713         }
5714
5715         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5716         {
5717                 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);
5718                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
5719                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true);
5720                 Mem_Free(pixels);
5721                 pixels = NULL;
5722         }
5723
5724         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5725         {
5726                 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);
5727                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
5728                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true);
5729                 Mem_Free(pixels);
5730                 pixels = NULL;
5731         }
5732
5733         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5734         {
5735                 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);
5736                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
5737                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true);
5738                 Mem_Free(pixels);
5739                 pixels = NULL;
5740         }
5741
5742         if (basepixels)
5743                 Mem_Free(basepixels);
5744
5745         return skinframe;
5746 }
5747
5748 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
5749 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
5750 {
5751         int i;
5752         unsigned char *temp1, *temp2;
5753         skinframe_t *skinframe;
5754
5755         if (cls.state == ca_dedicated)
5756                 return NULL;
5757
5758         // if already loaded just return it, otherwise make a new skinframe
5759         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
5760         if (skinframe && skinframe->base)
5761                 return skinframe;
5762
5763         skinframe->stain = NULL;
5764         skinframe->merged = NULL;
5765         skinframe->base = NULL;
5766         skinframe->pants = NULL;
5767         skinframe->shirt = NULL;
5768         skinframe->nmap = NULL;
5769         skinframe->gloss = NULL;
5770         skinframe->glow = NULL;
5771         skinframe->fog = NULL;
5772         skinframe->reflect = NULL;
5773         skinframe->hasalpha = false;
5774
5775         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5776         if (!skindata)
5777                 return NULL;
5778
5779         if (developer_loading.integer)
5780                 Con_Printf("loading 32bit skin \"%s\"\n", name);
5781
5782         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
5783         {
5784                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5785                 temp2 = temp1 + width * height * 4;
5786                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5787                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5788                 Mem_Free(temp1);
5789         }
5790         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5791         if (textureflags & TEXF_ALPHA)
5792         {
5793                 for (i = 3;i < width * height * 4;i += 4)
5794                 {
5795                         if (skindata[i] < 255)
5796                         {
5797                                 skinframe->hasalpha = true;
5798                                 break;
5799                         }
5800                 }
5801                 if (r_loadfog && skinframe->hasalpha)
5802                 {
5803                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
5804                         memcpy(fogpixels, skindata, width * height * 4);
5805                         for (i = 0;i < width * height * 4;i += 4)
5806                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
5807                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5808                         Mem_Free(fogpixels);
5809                 }
5810         }
5811
5812         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
5813         //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]);
5814
5815         return skinframe;
5816 }
5817
5818 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
5819 {
5820         int i;
5821         int featuresmask;
5822         skinframe_t *skinframe;
5823
5824         if (cls.state == ca_dedicated)
5825                 return NULL;
5826
5827         // if already loaded just return it, otherwise make a new skinframe
5828         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5829         if (skinframe && skinframe->base)
5830                 return skinframe;
5831
5832         skinframe->stain = NULL;
5833         skinframe->merged = NULL;
5834         skinframe->base = NULL;
5835         skinframe->pants = NULL;
5836         skinframe->shirt = NULL;
5837         skinframe->nmap = NULL;
5838         skinframe->gloss = NULL;
5839         skinframe->glow = NULL;
5840         skinframe->fog = NULL;
5841         skinframe->reflect = NULL;
5842         skinframe->hasalpha = false;
5843
5844         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5845         if (!skindata)
5846                 return NULL;
5847
5848         if (developer_loading.integer)
5849                 Con_Printf("loading quake skin \"%s\"\n", name);
5850
5851         // 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)
5852         skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
5853         memcpy(skinframe->qpixels, skindata, width*height);
5854         skinframe->qwidth = width;
5855         skinframe->qheight = height;
5856
5857         featuresmask = 0;
5858         for (i = 0;i < width * height;i++)
5859                 featuresmask |= palette_featureflags[skindata[i]];
5860
5861         skinframe->hasalpha = false;
5862         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
5863         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
5864         skinframe->qgeneratemerged = true;
5865         skinframe->qgeneratebase = skinframe->qhascolormapping;
5866         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
5867
5868         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
5869         //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]);
5870
5871         return skinframe;
5872 }
5873
5874 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
5875 {
5876         int width;
5877         int height;
5878         unsigned char *skindata;
5879
5880         if (!skinframe->qpixels)
5881                 return;
5882
5883         if (!skinframe->qhascolormapping)
5884                 colormapped = false;
5885
5886         if (colormapped)
5887         {
5888                 if (!skinframe->qgeneratebase)
5889                         return;
5890         }
5891         else
5892         {
5893                 if (!skinframe->qgeneratemerged)
5894                         return;
5895         }
5896
5897         width = skinframe->qwidth;
5898         height = skinframe->qheight;
5899         skindata = skinframe->qpixels;
5900
5901         if (skinframe->qgeneratenmap)
5902         {
5903                 unsigned char *temp1, *temp2;
5904                 skinframe->qgeneratenmap = false;
5905                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5906                 temp2 = temp1 + width * height * 4;
5907                 // use either a custom palette or the quake palette
5908                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
5909                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5910                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5911                 Mem_Free(temp1);
5912         }
5913
5914         if (skinframe->qgenerateglow)
5915         {
5916                 skinframe->qgenerateglow = false;
5917                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
5918         }
5919
5920         if (colormapped)
5921         {
5922                 skinframe->qgeneratebase = false;
5923                 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);
5924                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
5925                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
5926         }
5927         else
5928         {
5929                 skinframe->qgeneratemerged = false;
5930                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
5931         }
5932
5933         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
5934         {
5935                 Mem_Free(skinframe->qpixels);
5936                 skinframe->qpixels = NULL;
5937         }
5938 }
5939
5940 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)
5941 {
5942         int i;
5943         skinframe_t *skinframe;
5944
5945         if (cls.state == ca_dedicated)
5946                 return NULL;
5947
5948         // if already loaded just return it, otherwise make a new skinframe
5949         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5950         if (skinframe && skinframe->base)
5951                 return skinframe;
5952
5953         skinframe->stain = NULL;
5954         skinframe->merged = NULL;
5955         skinframe->base = NULL;
5956         skinframe->pants = NULL;
5957         skinframe->shirt = NULL;
5958         skinframe->nmap = NULL;
5959         skinframe->gloss = NULL;
5960         skinframe->glow = NULL;
5961         skinframe->fog = NULL;
5962         skinframe->reflect = NULL;
5963         skinframe->hasalpha = false;
5964
5965         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5966         if (!skindata)
5967                 return NULL;
5968
5969         if (developer_loading.integer)
5970                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
5971
5972         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
5973         if (textureflags & TEXF_ALPHA)
5974         {
5975                 for (i = 0;i < width * height;i++)
5976                 {
5977                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
5978                         {
5979                                 skinframe->hasalpha = true;
5980                                 break;
5981                         }
5982                 }
5983                 if (r_loadfog && skinframe->hasalpha)
5984                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
5985         }
5986
5987         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
5988         //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]);
5989
5990         return skinframe;
5991 }
5992
5993 skinframe_t *R_SkinFrame_LoadMissing(void)
5994 {
5995         skinframe_t *skinframe;
5996
5997         if (cls.state == ca_dedicated)
5998                 return NULL;
5999
6000         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6001         skinframe->stain = NULL;
6002         skinframe->merged = NULL;
6003         skinframe->base = NULL;
6004         skinframe->pants = NULL;
6005         skinframe->shirt = NULL;
6006         skinframe->nmap = NULL;
6007         skinframe->gloss = NULL;
6008         skinframe->glow = NULL;
6009         skinframe->fog = NULL;
6010         skinframe->reflect = NULL;
6011         skinframe->hasalpha = false;
6012
6013         skinframe->avgcolor[0] = rand() / RAND_MAX;
6014         skinframe->avgcolor[1] = rand() / RAND_MAX;
6015         skinframe->avgcolor[2] = rand() / RAND_MAX;
6016         skinframe->avgcolor[3] = 1;
6017
6018         return skinframe;
6019 }
6020
6021 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6022 typedef struct suffixinfo_s
6023 {
6024         char *suffix;
6025         qboolean flipx, flipy, flipdiagonal;
6026 }
6027 suffixinfo_t;
6028 static suffixinfo_t suffix[3][6] =
6029 {
6030         {
6031                 {"px",   false, false, false},
6032                 {"nx",   false, false, false},
6033                 {"py",   false, false, false},
6034                 {"ny",   false, false, false},
6035                 {"pz",   false, false, false},
6036                 {"nz",   false, false, false}
6037         },
6038         {
6039                 {"posx", false, false, false},
6040                 {"negx", false, false, false},
6041                 {"posy", false, false, false},
6042                 {"negy", false, false, false},
6043                 {"posz", false, false, false},
6044                 {"negz", false, false, false}
6045         },
6046         {
6047                 {"rt",    true, false,  true},
6048                 {"lf",   false,  true,  true},
6049                 {"ft",    true,  true, false},
6050                 {"bk",   false, false, false},
6051                 {"up",    true, false,  true},
6052                 {"dn",    true, false,  true}
6053         }
6054 };
6055
6056 static int componentorder[4] = {0, 1, 2, 3};
6057
6058 rtexture_t *R_LoadCubemap(const char *basename)
6059 {
6060         int i, j, cubemapsize;
6061         unsigned char *cubemappixels, *image_buffer;
6062         rtexture_t *cubemaptexture;
6063         char name[256];
6064         // must start 0 so the first loadimagepixels has no requested width/height
6065         cubemapsize = 0;
6066         cubemappixels = NULL;
6067         cubemaptexture = NULL;
6068         // keep trying different suffix groups (posx, px, rt) until one loads
6069         for (j = 0;j < 3 && !cubemappixels;j++)
6070         {
6071                 // load the 6 images in the suffix group
6072                 for (i = 0;i < 6;i++)
6073                 {
6074                         // generate an image name based on the base and and suffix
6075                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6076                         // load it
6077                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer)))
6078                         {
6079                                 // an image loaded, make sure width and height are equal
6080                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6081                                 {
6082                                         // if this is the first image to load successfully, allocate the cubemap memory
6083                                         if (!cubemappixels && image_width >= 1)
6084                                         {
6085                                                 cubemapsize = image_width;
6086                                                 // note this clears to black, so unavailable sides are black
6087                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6088                                         }
6089                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6090                                         if (cubemappixels)
6091                                                 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);
6092                                 }
6093                                 else
6094                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6095                                 // free the image
6096                                 Mem_Free(image_buffer);
6097                         }
6098                 }
6099         }
6100         // if a cubemap loaded, upload it
6101         if (cubemappixels)
6102         {
6103                 if (developer_loading.integer)
6104                         Con_Printf("loading cubemap \"%s\"\n", basename);
6105
6106                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR, NULL);
6107                 Mem_Free(cubemappixels);
6108         }
6109         else
6110         {
6111                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6112                 if (developer_loading.integer)
6113                 {
6114                         Con_Printf("(tried tried images ");
6115                         for (j = 0;j < 3;j++)
6116                                 for (i = 0;i < 6;i++)
6117                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
6118                         Con_Print(" and was unable to find any of them).\n");
6119                 }
6120         }
6121         return cubemaptexture;
6122 }
6123
6124 rtexture_t *R_GetCubemap(const char *basename)
6125 {
6126         int i;
6127         for (i = 0;i < r_texture_numcubemaps;i++)
6128                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6129                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6130         if (i >= MAX_CUBEMAPS)
6131                 return r_texture_whitecube;
6132         r_texture_numcubemaps++;
6133         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6134         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6135         return r_texture_cubemaps[i].texture;
6136 }
6137
6138 void R_FreeCubemaps(void)
6139 {
6140         int i;
6141         for (i = 0;i < r_texture_numcubemaps;i++)
6142         {
6143                 if (developer_loading.integer)
6144                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6145                 if (r_texture_cubemaps[i].texture)
6146                         R_FreeTexture(r_texture_cubemaps[i].texture);
6147         }
6148         r_texture_numcubemaps = 0;
6149 }
6150
6151 void R_Main_FreeViewCache(void)
6152 {
6153         if (r_refdef.viewcache.entityvisible)
6154                 Mem_Free(r_refdef.viewcache.entityvisible);
6155         if (r_refdef.viewcache.world_pvsbits)
6156                 Mem_Free(r_refdef.viewcache.world_pvsbits);
6157         if (r_refdef.viewcache.world_leafvisible)
6158                 Mem_Free(r_refdef.viewcache.world_leafvisible);
6159         if (r_refdef.viewcache.world_surfacevisible)
6160                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6161         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6162 }
6163
6164 void R_Main_ResizeViewCache(void)
6165 {
6166         int numentities = r_refdef.scene.numentities;
6167         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6168         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6169         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6170         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6171         if (r_refdef.viewcache.maxentities < numentities)
6172         {
6173                 r_refdef.viewcache.maxentities = numentities;
6174                 if (r_refdef.viewcache.entityvisible)
6175                         Mem_Free(r_refdef.viewcache.entityvisible);
6176                 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6177         }
6178         if (r_refdef.viewcache.world_numclusters != numclusters)
6179         {
6180                 r_refdef.viewcache.world_numclusters = numclusters;
6181                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6182                 if (r_refdef.viewcache.world_pvsbits)
6183                         Mem_Free(r_refdef.viewcache.world_pvsbits);
6184                 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6185         }
6186         if (r_refdef.viewcache.world_numleafs != numleafs)
6187         {
6188                 r_refdef.viewcache.world_numleafs = numleafs;
6189                 if (r_refdef.viewcache.world_leafvisible)
6190                         Mem_Free(r_refdef.viewcache.world_leafvisible);
6191                 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6192         }
6193         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6194         {
6195                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6196                 if (r_refdef.viewcache.world_surfacevisible)
6197                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
6198                 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6199         }
6200 }
6201
6202 extern rtexture_t *loadingscreentexture;
6203 void gl_main_start(void)
6204 {
6205         loadingscreentexture = NULL;
6206         r_texture_blanknormalmap = NULL;
6207         r_texture_white = NULL;
6208         r_texture_grey128 = NULL;
6209         r_texture_black = NULL;
6210         r_texture_whitecube = NULL;
6211         r_texture_normalizationcube = NULL;
6212         r_texture_fogattenuation = NULL;
6213         r_texture_fogheighttexture = NULL;
6214         r_texture_gammaramps = NULL;
6215         r_texture_numcubemaps = 0;
6216
6217         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
6218         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6219
6220         switch(vid.renderpath)
6221         {
6222         case RENDERPATH_GL20:
6223         case RENDERPATH_CGGL:
6224                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6225                 Cvar_SetValueQuick(&gl_combine, 1);
6226                 Cvar_SetValueQuick(&r_glsl, 1);
6227                 r_loadnormalmap = true;
6228                 r_loadgloss = true;
6229                 r_loadfog = false;
6230                 break;
6231         case RENDERPATH_GL13:
6232                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6233                 Cvar_SetValueQuick(&gl_combine, 1);
6234                 Cvar_SetValueQuick(&r_glsl, 0);
6235                 r_loadnormalmap = false;
6236                 r_loadgloss = false;
6237                 r_loadfog = true;
6238                 break;
6239         case RENDERPATH_GL11:
6240                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6241                 Cvar_SetValueQuick(&gl_combine, 0);
6242                 Cvar_SetValueQuick(&r_glsl, 0);
6243                 r_loadnormalmap = false;
6244                 r_loadgloss = false;
6245                 r_loadfog = true;
6246                 break;
6247         }
6248
6249         R_AnimCache_Free();
6250         R_FrameData_Reset();
6251
6252         r_numqueries = 0;
6253         r_maxqueries = 0;
6254         memset(r_queries, 0, sizeof(r_queries));
6255
6256         r_qwskincache = NULL;
6257         r_qwskincache_size = 0;
6258
6259         // set up r_skinframe loading system for textures
6260         memset(&r_skinframe, 0, sizeof(r_skinframe));
6261         r_skinframe.loadsequence = 1;
6262         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
6263
6264         r_main_texturepool = R_AllocTexturePool();
6265         R_BuildBlankTextures();
6266         R_BuildNoTexture();
6267         if (vid.support.arb_texture_cube_map)
6268         {
6269                 R_BuildWhiteCube();
6270                 R_BuildNormalizationCube();
6271         }
6272         r_texture_fogattenuation = NULL;
6273         r_texture_fogheighttexture = NULL;
6274         r_texture_gammaramps = NULL;
6275         //r_texture_fogintensity = NULL;
6276         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6277         memset(&r_waterstate, 0, sizeof(r_waterstate));
6278         r_glsl_permutation = NULL;
6279         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6280         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
6281         glslshaderstring = NULL;
6282 #ifdef SUPPORTCG
6283         r_cg_permutation = NULL;
6284         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
6285         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
6286         cgshaderstring = NULL;
6287 #endif
6288         memset(&r_svbsp, 0, sizeof (r_svbsp));
6289
6290         r_refdef.fogmasktable_density = 0;
6291 }
6292
6293 void gl_main_shutdown(void)
6294 {
6295         R_AnimCache_Free();
6296         R_FrameData_Reset();
6297
6298         R_Main_FreeViewCache();
6299
6300         if (r_maxqueries)
6301                 qglDeleteQueriesARB(r_maxqueries, r_queries);
6302
6303         r_numqueries = 0;
6304         r_maxqueries = 0;
6305         memset(r_queries, 0, sizeof(r_queries));
6306
6307         r_qwskincache = NULL;
6308         r_qwskincache_size = 0;
6309
6310         // clear out the r_skinframe state
6311         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
6312         memset(&r_skinframe, 0, sizeof(r_skinframe));
6313
6314         if (r_svbsp.nodes)
6315                 Mem_Free(r_svbsp.nodes);
6316         memset(&r_svbsp, 0, sizeof (r_svbsp));
6317         R_FreeTexturePool(&r_main_texturepool);
6318         loadingscreentexture = NULL;
6319         r_texture_blanknormalmap = NULL;
6320         r_texture_white = NULL;
6321         r_texture_grey128 = NULL;
6322         r_texture_black = NULL;
6323         r_texture_whitecube = NULL;
6324         r_texture_normalizationcube = NULL;
6325         r_texture_fogattenuation = NULL;
6326         r_texture_fogheighttexture = NULL;
6327         r_texture_gammaramps = NULL;
6328         r_texture_numcubemaps = 0;
6329         //r_texture_fogintensity = NULL;
6330         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6331         memset(&r_waterstate, 0, sizeof(r_waterstate));
6332         r_glsl_permutation = NULL;
6333         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6334         glslshaderstring = NULL;
6335 #ifdef SUPPORTCG
6336         r_cg_permutation = NULL;
6337         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
6338         cgshaderstring = NULL;
6339 #endif
6340         R_GLSL_Restart_f();
6341 }
6342
6343 extern void CL_ParseEntityLump(char *entitystring);
6344 void gl_main_newmap(void)
6345 {
6346         // FIXME: move this code to client
6347         int l;
6348         char *entities, entname[MAX_QPATH];
6349         if (r_qwskincache)
6350                 Mem_Free(r_qwskincache);
6351         r_qwskincache = NULL;
6352         r_qwskincache_size = 0;
6353         if (cl.worldmodel)
6354         {
6355                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
6356                 l = (int)strlen(entname) - 4;
6357                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
6358                 {
6359                         memcpy(entname + l, ".ent", 5);
6360                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
6361                         {
6362                                 CL_ParseEntityLump(entities);
6363                                 Mem_Free(entities);
6364                                 return;
6365                         }
6366                 }
6367                 if (cl.worldmodel->brush.entities)
6368                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
6369         }
6370         R_Main_FreeViewCache();
6371
6372         R_FrameData_Reset();
6373 }
6374
6375 void GL_Main_Init(void)
6376 {
6377         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
6378
6379         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
6380         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
6381         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
6382         if (gamemode == GAME_NEHAHRA)
6383         {
6384                 Cvar_RegisterVariable (&gl_fogenable);
6385                 Cvar_RegisterVariable (&gl_fogdensity);
6386                 Cvar_RegisterVariable (&gl_fogred);
6387                 Cvar_RegisterVariable (&gl_foggreen);
6388                 Cvar_RegisterVariable (&gl_fogblue);
6389                 Cvar_RegisterVariable (&gl_fogstart);
6390                 Cvar_RegisterVariable (&gl_fogend);
6391                 Cvar_RegisterVariable (&gl_skyclip);
6392         }
6393         Cvar_RegisterVariable(&r_motionblur);
6394         Cvar_RegisterVariable(&r_motionblur_maxblur);
6395         Cvar_RegisterVariable(&r_motionblur_bmin);
6396         Cvar_RegisterVariable(&r_motionblur_vmin);
6397         Cvar_RegisterVariable(&r_motionblur_vmax);
6398         Cvar_RegisterVariable(&r_motionblur_vcoeff);
6399         Cvar_RegisterVariable(&r_motionblur_randomize);
6400         Cvar_RegisterVariable(&r_damageblur);
6401         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
6402         Cvar_RegisterVariable(&r_equalize_entities_minambient);
6403         Cvar_RegisterVariable(&r_equalize_entities_by);
6404         Cvar_RegisterVariable(&r_equalize_entities_to);
6405         Cvar_RegisterVariable(&r_depthfirst);
6406         Cvar_RegisterVariable(&r_useinfinitefarclip);
6407         Cvar_RegisterVariable(&r_farclip_base);
6408         Cvar_RegisterVariable(&r_farclip_world);
6409         Cvar_RegisterVariable(&r_nearclip);
6410         Cvar_RegisterVariable(&r_showbboxes);
6411         Cvar_RegisterVariable(&r_showsurfaces);
6412         Cvar_RegisterVariable(&r_showtris);
6413         Cvar_RegisterVariable(&r_shownormals);
6414         Cvar_RegisterVariable(&r_showlighting);
6415         Cvar_RegisterVariable(&r_showshadowvolumes);
6416         Cvar_RegisterVariable(&r_showcollisionbrushes);
6417         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
6418         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
6419         Cvar_RegisterVariable(&r_showdisabledepthtest);
6420         Cvar_RegisterVariable(&r_drawportals);
6421         Cvar_RegisterVariable(&r_drawentities);
6422         Cvar_RegisterVariable(&r_cullentities_trace);
6423         Cvar_RegisterVariable(&r_cullentities_trace_samples);
6424         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
6425         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
6426         Cvar_RegisterVariable(&r_cullentities_trace_delay);
6427         Cvar_RegisterVariable(&r_drawviewmodel);
6428         Cvar_RegisterVariable(&r_drawexteriormodel);
6429         Cvar_RegisterVariable(&r_speeds);
6430         Cvar_RegisterVariable(&r_fullbrights);
6431         Cvar_RegisterVariable(&r_wateralpha);
6432         Cvar_RegisterVariable(&r_dynamic);
6433         Cvar_RegisterVariable(&r_fullbright);
6434         Cvar_RegisterVariable(&r_shadows);
6435         Cvar_RegisterVariable(&r_shadows_darken);
6436         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
6437         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
6438         Cvar_RegisterVariable(&r_shadows_throwdistance);
6439         Cvar_RegisterVariable(&r_shadows_throwdirection);
6440         Cvar_RegisterVariable(&r_shadows_focus);
6441         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
6442         Cvar_RegisterVariable(&r_q1bsp_skymasking);
6443         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
6444         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
6445         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
6446         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
6447         Cvar_RegisterVariable(&r_fog_exp2);
6448         Cvar_RegisterVariable(&r_drawfog);
6449         Cvar_RegisterVariable(&r_transparentdepthmasking);
6450         Cvar_RegisterVariable(&r_texture_dds_load);
6451         Cvar_RegisterVariable(&r_texture_dds_save);
6452         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
6453         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
6454         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
6455         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
6456         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
6457         Cvar_RegisterVariable(&r_textureunits);
6458         Cvar_RegisterVariable(&gl_combine);
6459         Cvar_RegisterVariable(&r_glsl);
6460         Cvar_RegisterVariable(&r_glsl_deluxemapping);
6461         Cvar_RegisterVariable(&r_glsl_offsetmapping);
6462         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
6463         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
6464         Cvar_RegisterVariable(&r_glsl_postprocess);
6465         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
6466         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
6467         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
6468         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
6469         Cvar_RegisterVariable(&r_water);
6470         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
6471         Cvar_RegisterVariable(&r_water_clippingplanebias);
6472         Cvar_RegisterVariable(&r_water_refractdistort);
6473         Cvar_RegisterVariable(&r_water_reflectdistort);
6474         Cvar_RegisterVariable(&r_lerpsprites);
6475         Cvar_RegisterVariable(&r_lerpmodels);
6476         Cvar_RegisterVariable(&r_lerplightstyles);
6477         Cvar_RegisterVariable(&r_waterscroll);
6478         Cvar_RegisterVariable(&r_bloom);
6479         Cvar_RegisterVariable(&r_bloom_colorscale);
6480         Cvar_RegisterVariable(&r_bloom_brighten);
6481         Cvar_RegisterVariable(&r_bloom_blur);
6482         Cvar_RegisterVariable(&r_bloom_resolution);
6483         Cvar_RegisterVariable(&r_bloom_colorexponent);
6484         Cvar_RegisterVariable(&r_bloom_colorsubtract);
6485         Cvar_RegisterVariable(&r_hdr);
6486         Cvar_RegisterVariable(&r_hdr_scenebrightness);
6487         Cvar_RegisterVariable(&r_hdr_glowintensity);
6488         Cvar_RegisterVariable(&r_hdr_range);
6489         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
6490         Cvar_RegisterVariable(&developer_texturelogging);
6491         Cvar_RegisterVariable(&gl_lightmaps);
6492         Cvar_RegisterVariable(&r_test);
6493         Cvar_RegisterVariable(&r_batchmode);
6494         Cvar_RegisterVariable(&r_glsl_saturation);
6495         Cvar_RegisterVariable(&r_framedatasize);
6496         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
6497                 Cvar_SetValue("r_fullbrights", 0);
6498         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
6499
6500         Cvar_RegisterVariable(&r_track_sprites);
6501         Cvar_RegisterVariable(&r_track_sprites_flags);
6502         Cvar_RegisterVariable(&r_track_sprites_scalew);
6503         Cvar_RegisterVariable(&r_track_sprites_scaleh);
6504         Cvar_RegisterVariable(&r_overheadsprites_perspective);
6505         Cvar_RegisterVariable(&r_overheadsprites_pushback);
6506 }
6507
6508 extern void R_Textures_Init(void);
6509 extern void GL_Draw_Init(void);
6510 extern void GL_Main_Init(void);
6511 extern void R_Shadow_Init(void);
6512 extern void R_Sky_Init(void);
6513 extern void GL_Surf_Init(void);
6514 extern void R_Particles_Init(void);
6515 extern void R_Explosion_Init(void);
6516 extern void gl_backend_init(void);
6517 extern void Sbar_Init(void);
6518 extern void R_LightningBeams_Init(void);
6519 extern void Mod_RenderInit(void);
6520 extern void Font_Init(void);
6521
6522 void Render_Init(void)
6523 {
6524         gl_backend_init();
6525         R_Textures_Init();
6526         GL_Main_Init();
6527         Font_Init();
6528         GL_Draw_Init();
6529         R_Shadow_Init();
6530         R_Sky_Init();
6531         GL_Surf_Init();
6532         Sbar_Init();
6533         R_Particles_Init();
6534         R_Explosion_Init();
6535         R_LightningBeams_Init();
6536         Mod_RenderInit();
6537 }
6538
6539 /*
6540 ===============
6541 GL_Init
6542 ===============
6543 */
6544 extern char *ENGINE_EXTENSIONS;
6545 void GL_Init (void)
6546 {
6547         gl_renderer = (const char *)qglGetString(GL_RENDERER);
6548         gl_vendor = (const char *)qglGetString(GL_VENDOR);
6549         gl_version = (const char *)qglGetString(GL_VERSION);
6550         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
6551
6552         if (!gl_extensions)
6553                 gl_extensions = "";
6554         if (!gl_platformextensions)
6555                 gl_platformextensions = "";
6556
6557         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
6558         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
6559         Con_Printf("GL_VERSION: %s\n", gl_version);
6560         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
6561         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
6562
6563         VID_CheckExtensions();
6564
6565         // LordHavoc: report supported extensions
6566         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
6567
6568         // clear to black (loading plaque will be seen over this)
6569         CHECKGLERROR
6570         qglClearColor(0,0,0,1);CHECKGLERROR
6571         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
6572 }
6573
6574 int R_CullBox(const vec3_t mins, const vec3_t maxs)
6575 {
6576         int i;
6577         mplane_t *p;
6578         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6579         {
6580                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
6581                 if (i == 4)
6582                         continue;
6583                 p = r_refdef.view.frustum + i;
6584                 switch(p->signbits)
6585                 {
6586                 default:
6587                 case 0:
6588                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6589                                 return true;
6590                         break;
6591                 case 1:
6592                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6593                                 return true;
6594                         break;
6595                 case 2:
6596                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6597                                 return true;
6598                         break;
6599                 case 3:
6600                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6601                                 return true;
6602                         break;
6603                 case 4:
6604                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6605                                 return true;
6606                         break;
6607                 case 5:
6608                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6609                                 return true;
6610                         break;
6611                 case 6:
6612                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6613                                 return true;
6614                         break;
6615                 case 7:
6616                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6617                                 return true;
6618                         break;
6619                 }
6620         }
6621         return false;
6622 }
6623
6624 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
6625 {
6626         int i;
6627         const mplane_t *p;
6628         for (i = 0;i < numplanes;i++)
6629         {
6630                 p = planes + i;
6631                 switch(p->signbits)
6632                 {
6633                 default:
6634                 case 0:
6635                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6636                                 return true;
6637                         break;
6638                 case 1:
6639                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6640                                 return true;
6641                         break;
6642                 case 2:
6643                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6644                                 return true;
6645                         break;
6646                 case 3:
6647                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6648                                 return true;
6649                         break;
6650                 case 4:
6651                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6652                                 return true;
6653                         break;
6654                 case 5:
6655                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6656                                 return true;
6657                         break;
6658                 case 6:
6659                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6660                                 return true;
6661                         break;
6662                 case 7:
6663                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6664                                 return true;
6665                         break;
6666                 }
6667         }
6668         return false;
6669 }
6670
6671 //==================================================================================
6672
6673 // LordHavoc: this stores temporary data used within the same frame
6674
6675 qboolean r_framedata_failed;
6676 static size_t r_framedata_size;
6677 static size_t r_framedata_current;
6678 static void *r_framedata_base;
6679
6680 void R_FrameData_Reset(void)
6681 {
6682         if (r_framedata_base)
6683                 Mem_Free(r_framedata_base);
6684         r_framedata_base = NULL;
6685         r_framedata_size = 0;
6686         r_framedata_current = 0;
6687         r_framedata_failed = false;
6688 }
6689
6690 void R_FrameData_NewFrame(void)
6691 {
6692         size_t wantedsize;
6693         if (r_framedata_failed)
6694                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
6695         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
6696         wantedsize = bound(65536, wantedsize, 128*1024*1024);
6697         if (r_framedata_size != wantedsize)
6698         {
6699                 r_framedata_size = wantedsize;
6700                 if (r_framedata_base)
6701                         Mem_Free(r_framedata_base);
6702                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
6703         }
6704         r_framedata_current = 0;
6705         r_framedata_failed = false;
6706 }
6707
6708 void *R_FrameData_Alloc(size_t size)
6709 {
6710         void *data;
6711
6712         // align to 16 byte boundary
6713         size = (size + 15) & ~15;
6714         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
6715         r_framedata_current += size;
6716
6717         // check overflow
6718         if (r_framedata_current > r_framedata_size)
6719                 r_framedata_failed = true;
6720
6721         // return NULL on everything after a failure
6722         if (r_framedata_failed)
6723                 return NULL;
6724
6725         return data;
6726 }
6727
6728 void *R_FrameData_Store(size_t size, void *data)
6729 {
6730         void *d = R_FrameData_Alloc(size);
6731         if (d)
6732                 memcpy(d, data, size);
6733         return d;
6734 }
6735
6736 //==================================================================================
6737
6738 // LordHavoc: animcache originally written by Echon, rewritten since then
6739
6740 /**
6741  * Animation cache prevents re-generating mesh data for an animated model
6742  * multiple times in one frame for lighting, shadowing, reflections, etc.
6743  */
6744
6745 void R_AnimCache_Free(void)
6746 {
6747 }
6748
6749 void R_AnimCache_ClearCache(void)
6750 {
6751         int i;
6752         entity_render_t *ent;
6753
6754         for (i = 0;i < r_refdef.scene.numentities;i++)
6755         {
6756                 ent = r_refdef.scene.entities[i];
6757                 ent->animcache_vertex3f = NULL;
6758                 ent->animcache_normal3f = NULL;
6759                 ent->animcache_svector3f = NULL;
6760                 ent->animcache_tvector3f = NULL;
6761         }
6762 }
6763
6764 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6765 {
6766         dp_model_t *model = ent->model;
6767         int numvertices;
6768         // see if it's already cached this frame
6769         if (ent->animcache_vertex3f)
6770         {
6771                 // add normals/tangents if needed
6772                 if (wantnormals || wanttangents)
6773                 {
6774                         if (ent->animcache_normal3f)
6775                                 wantnormals = false;
6776                         if (ent->animcache_svector3f)
6777                                 wanttangents = false;
6778                         if (wantnormals || wanttangents)
6779                         {
6780                                 numvertices = model->surfmesh.num_vertices;
6781                                 if (wantnormals)
6782                                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6783                                 if (wanttangents)
6784                                 {
6785                                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6786                                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6787                                 }
6788                                 if (!r_framedata_failed)
6789                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
6790                         }
6791                 }
6792         }
6793         else
6794         {
6795                 // see if this ent is worth caching
6796                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
6797                         return false;
6798                 // get some memory for this entity and generate mesh data
6799                 numvertices = model->surfmesh.num_vertices;
6800                 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6801                 if (wantnormals)
6802                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6803                 if (wanttangents)
6804                 {
6805                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6806                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6807                 }
6808                 if (!r_framedata_failed)
6809                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
6810         }
6811         return !r_framedata_failed;
6812 }
6813
6814 void R_AnimCache_CacheVisibleEntities(void)
6815 {
6816         int i;
6817         qboolean wantnormals = !r_showsurfaces.integer;
6818         qboolean wanttangents = !r_showsurfaces.integer;
6819
6820         switch(vid.renderpath)
6821         {
6822         case RENDERPATH_GL20:
6823         case RENDERPATH_CGGL:
6824                 break;
6825         case RENDERPATH_GL13:
6826         case RENDERPATH_GL11:
6827                 wanttangents = false;
6828                 break;
6829         }
6830
6831         // TODO: thread this
6832         // NOTE: R_PrepareRTLights() also caches entities
6833
6834         for (i = 0;i < r_refdef.scene.numentities;i++)
6835                 if (r_refdef.viewcache.entityvisible[i])
6836                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
6837 }
6838
6839 //==================================================================================
6840
6841 static void R_View_UpdateEntityLighting (void)
6842 {
6843         int i;
6844         entity_render_t *ent;
6845         vec3_t tempdiffusenormal, avg;
6846         vec_t f, fa, fd, fdd;
6847         qboolean skipunseen = r_shadows.integer != 1 || R_Shadow_ShadowMappingEnabled();
6848
6849         for (i = 0;i < r_refdef.scene.numentities;i++)
6850         {
6851                 ent = r_refdef.scene.entities[i];
6852
6853                 // skip unseen models
6854                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
6855                         continue;
6856
6857                 // skip bsp models
6858                 if (ent->model && ent->model->brush.num_leafs)
6859                 {
6860                         // TODO: use modellight for r_ambient settings on world?
6861                         VectorSet(ent->modellight_ambient, 0, 0, 0);
6862                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
6863                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
6864                         continue;
6865                 }
6866
6867                 // fetch the lighting from the worldmodel data
6868                 VectorClear(ent->modellight_ambient);
6869                 VectorClear(ent->modellight_diffuse);
6870                 VectorClear(tempdiffusenormal);
6871                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
6872                 {
6873                         vec3_t org;
6874                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6875                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
6876                         if(ent->flags & RENDER_EQUALIZE)
6877                         {
6878                                 // first fix up ambient lighting...
6879                                 if(r_equalize_entities_minambient.value > 0)
6880                                 {
6881                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
6882                                         if(fd > 0)
6883                                         {
6884                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
6885                                                 if(fa < r_equalize_entities_minambient.value * fd)
6886                                                 {
6887                                                         // solve:
6888                                                         //   fa'/fd' = minambient
6889                                                         //   fa'+0.25*fd' = fa+0.25*fd
6890                                                         //   ...
6891                                                         //   fa' = fd' * minambient
6892                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
6893                                                         //   ...
6894                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
6895                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
6896                                                         //   ...
6897                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
6898                                                         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
6899                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
6900                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6901                                                 }
6902                                         }
6903                                 }
6904
6905                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
6906                                 {
6907                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
6908                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
6909                                         if(f > 0)
6910                                         {
6911                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
6912                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
6913                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6914                                         }
6915                                 }
6916                         }
6917                 }
6918                 else // highly rare
6919                         VectorSet(ent->modellight_ambient, 1, 1, 1);
6920
6921                 // move the light direction into modelspace coordinates for lighting code
6922                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
6923                 if(VectorLength2(ent->modellight_lightdir) == 0)
6924                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
6925                 VectorNormalize(ent->modellight_lightdir);
6926         }
6927 }
6928
6929 #define MAX_LINEOFSIGHTTRACES 64
6930
6931 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
6932 {
6933         int i;
6934         vec3_t boxmins, boxmaxs;
6935         vec3_t start;
6936         vec3_t end;
6937         dp_model_t *model = r_refdef.scene.worldmodel;
6938
6939         if (!model || !model->brush.TraceLineOfSight)
6940                 return true;
6941
6942         // expand the box a little
6943         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
6944         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
6945         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
6946         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
6947         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
6948         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
6949
6950         // return true if eye is inside enlarged box
6951         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
6952                 return true;
6953
6954         // try center
6955         VectorCopy(eye, start);
6956         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
6957         if (model->brush.TraceLineOfSight(model, start, end))
6958                 return true;
6959
6960         // try various random positions
6961         for (i = 0;i < numsamples;i++)
6962         {
6963                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
6964                 if (model->brush.TraceLineOfSight(model, start, end))
6965                         return true;
6966         }
6967
6968         return false;
6969 }
6970
6971
6972 static void R_View_UpdateEntityVisible (void)
6973 {
6974         int i;
6975         int renderimask;
6976         int samples;
6977         entity_render_t *ent;
6978
6979         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
6980                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
6981                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
6982                 :                                                          RENDER_EXTERIORMODEL;
6983         if (!r_drawviewmodel.integer)
6984                 renderimask |= RENDER_VIEWMODEL;
6985         if (!r_drawexteriormodel.integer)
6986                 renderimask |= RENDER_EXTERIORMODEL;
6987         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
6988         {
6989                 // worldmodel can check visibility
6990                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
6991                 for (i = 0;i < r_refdef.scene.numentities;i++)
6992                 {
6993                         ent = r_refdef.scene.entities[i];
6994                         if (!(ent->flags & renderimask))
6995                         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)))
6996                         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))
6997                                 r_refdef.viewcache.entityvisible[i] = true;
6998                 }
6999                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
7000                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
7001                 {
7002                         for (i = 0;i < r_refdef.scene.numentities;i++)
7003                         {
7004                                 ent = r_refdef.scene.entities[i];
7005                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
7006                                 {
7007                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
7008                                         if (samples < 0)
7009                                                 continue; // temp entities do pvs only
7010                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
7011                                                 ent->last_trace_visibility = realtime;
7012                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
7013                                                 r_refdef.viewcache.entityvisible[i] = 0;
7014                                 }
7015                         }
7016                 }
7017         }
7018         else
7019         {
7020                 // no worldmodel or it can't check visibility
7021                 for (i = 0;i < r_refdef.scene.numentities;i++)
7022                 {
7023                         ent = r_refdef.scene.entities[i];
7024                         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));
7025                 }
7026         }
7027 }
7028
7029 /// only used if skyrendermasked, and normally returns false
7030 int R_DrawBrushModelsSky (void)
7031 {
7032         int i, sky;
7033         entity_render_t *ent;
7034
7035         sky = false;
7036         for (i = 0;i < r_refdef.scene.numentities;i++)
7037         {
7038                 if (!r_refdef.viewcache.entityvisible[i])
7039                         continue;
7040                 ent = r_refdef.scene.entities[i];
7041                 if (!ent->model || !ent->model->DrawSky)
7042                         continue;
7043                 ent->model->DrawSky(ent);
7044                 sky = true;
7045         }
7046         return sky;
7047 }
7048
7049 static void R_DrawNoModel(entity_render_t *ent);
7050 static void R_DrawModels(void)
7051 {
7052         int i;
7053         entity_render_t *ent;
7054
7055         for (i = 0;i < r_refdef.scene.numentities;i++)
7056         {
7057                 if (!r_refdef.viewcache.entityvisible[i])
7058                         continue;
7059                 ent = r_refdef.scene.entities[i];
7060                 r_refdef.stats.entities++;
7061                 if (ent->model && ent->model->Draw != NULL)
7062                         ent->model->Draw(ent);
7063                 else
7064                         R_DrawNoModel(ent);
7065         }
7066 }
7067
7068 static void R_DrawModelsDepth(void)
7069 {
7070         int i;
7071         entity_render_t *ent;
7072
7073         for (i = 0;i < r_refdef.scene.numentities;i++)
7074         {
7075                 if (!r_refdef.viewcache.entityvisible[i])
7076                         continue;
7077                 ent = r_refdef.scene.entities[i];
7078                 if (ent->model && ent->model->DrawDepth != NULL)
7079                         ent->model->DrawDepth(ent);
7080         }
7081 }
7082
7083 static void R_DrawModelsDebug(void)
7084 {
7085         int i;
7086         entity_render_t *ent;
7087
7088         for (i = 0;i < r_refdef.scene.numentities;i++)
7089         {
7090                 if (!r_refdef.viewcache.entityvisible[i])
7091                         continue;
7092                 ent = r_refdef.scene.entities[i];
7093                 if (ent->model && ent->model->DrawDebug != NULL)
7094                         ent->model->DrawDebug(ent);
7095         }
7096 }
7097
7098 static void R_DrawModelsAddWaterPlanes(void)
7099 {
7100         int i;
7101         entity_render_t *ent;
7102
7103         for (i = 0;i < r_refdef.scene.numentities;i++)
7104         {
7105                 if (!r_refdef.viewcache.entityvisible[i])
7106                         continue;
7107                 ent = r_refdef.scene.entities[i];
7108                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
7109                         ent->model->DrawAddWaterPlanes(ent);
7110         }
7111 }
7112
7113 static void R_View_SetFrustum(void)
7114 {
7115         int i;
7116         double slopex, slopey;
7117         vec3_t forward, left, up, origin;
7118
7119         // we can't trust r_refdef.view.forward and friends in reflected scenes
7120         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
7121
7122 #if 0
7123         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
7124         r_refdef.view.frustum[0].normal[1] = 0 - 0;
7125         r_refdef.view.frustum[0].normal[2] = -1 - 0;
7126         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
7127         r_refdef.view.frustum[1].normal[1] = 0 + 0;
7128         r_refdef.view.frustum[1].normal[2] = -1 + 0;
7129         r_refdef.view.frustum[2].normal[0] = 0 - 0;
7130         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
7131         r_refdef.view.frustum[2].normal[2] = -1 - 0;
7132         r_refdef.view.frustum[3].normal[0] = 0 + 0;
7133         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
7134         r_refdef.view.frustum[3].normal[2] = -1 + 0;
7135 #endif
7136
7137 #if 0
7138         zNear = r_refdef.nearclip;
7139         nudge = 1.0 - 1.0 / (1<<23);
7140         r_refdef.view.frustum[4].normal[0] = 0 - 0;
7141         r_refdef.view.frustum[4].normal[1] = 0 - 0;
7142         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
7143         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
7144         r_refdef.view.frustum[5].normal[0] = 0 + 0;
7145         r_refdef.view.frustum[5].normal[1] = 0 + 0;
7146         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
7147         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
7148 #endif
7149
7150
7151
7152 #if 0
7153         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
7154         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
7155         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
7156         r_refdef.view.frustum[0].dist = m[15] - m[12];
7157
7158         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
7159         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
7160         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
7161         r_refdef.view.frustum[1].dist = m[15] + m[12];
7162
7163         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
7164         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
7165         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
7166         r_refdef.view.frustum[2].dist = m[15] - m[13];
7167
7168         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
7169         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
7170         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
7171         r_refdef.view.frustum[3].dist = m[15] + m[13];
7172
7173         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
7174         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
7175         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
7176         r_refdef.view.frustum[4].dist = m[15] - m[14];
7177
7178         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
7179         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
7180         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
7181         r_refdef.view.frustum[5].dist = m[15] + m[14];
7182 #endif
7183
7184         if (r_refdef.view.useperspective)
7185         {
7186                 slopex = 1.0 / r_refdef.view.frustum_x;
7187                 slopey = 1.0 / r_refdef.view.frustum_y;
7188                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
7189                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
7190                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
7191                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
7192                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7193
7194                 // Leaving those out was a mistake, those were in the old code, and they
7195                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
7196                 // I couldn't reproduce it after adding those normalizations. --blub
7197                 VectorNormalize(r_refdef.view.frustum[0].normal);
7198                 VectorNormalize(r_refdef.view.frustum[1].normal);
7199                 VectorNormalize(r_refdef.view.frustum[2].normal);
7200                 VectorNormalize(r_refdef.view.frustum[3].normal);
7201
7202                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
7203                 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]);
7204                 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]);
7205                 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]);
7206                 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]);
7207
7208                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
7209                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
7210                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
7211                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
7212                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7213         }
7214         else
7215         {
7216                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
7217                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
7218                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
7219                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
7220                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7221                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
7222                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
7223                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
7224                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
7225                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7226         }
7227         r_refdef.view.numfrustumplanes = 5;
7228
7229         if (r_refdef.view.useclipplane)
7230         {
7231                 r_refdef.view.numfrustumplanes = 6;
7232                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
7233         }
7234
7235         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7236                 PlaneClassify(r_refdef.view.frustum + i);
7237
7238         // LordHavoc: note to all quake engine coders, Quake had a special case
7239         // for 90 degrees which assumed a square view (wrong), so I removed it,
7240         // Quake2 has it disabled as well.
7241
7242         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
7243         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
7244         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
7245         //PlaneClassify(&frustum[0]);
7246
7247         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
7248         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
7249         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
7250         //PlaneClassify(&frustum[1]);
7251
7252         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
7253         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
7254         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
7255         //PlaneClassify(&frustum[2]);
7256
7257         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
7258         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
7259         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
7260         //PlaneClassify(&frustum[3]);
7261
7262         // nearclip plane
7263         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
7264         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
7265         //PlaneClassify(&frustum[4]);
7266 }
7267
7268 void R_View_Update(void)
7269 {
7270         R_Main_ResizeViewCache();
7271         R_View_SetFrustum();
7272         R_View_WorldVisibility(r_refdef.view.useclipplane);
7273         R_View_UpdateEntityVisible();
7274         R_View_UpdateEntityLighting();
7275 }
7276
7277 void R_SetupView(qboolean allowwaterclippingplane)
7278 {
7279         const float *customclipplane = NULL;
7280         float plane[4];
7281         if (r_refdef.view.useclipplane && allowwaterclippingplane)
7282         {
7283                 // LordHavoc: couldn't figure out how to make this approach the
7284                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
7285                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
7286                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
7287                         dist = r_refdef.view.clipplane.dist;
7288                 plane[0] = r_refdef.view.clipplane.normal[0];
7289                 plane[1] = r_refdef.view.clipplane.normal[1];
7290                 plane[2] = r_refdef.view.clipplane.normal[2];
7291                 plane[3] = dist;
7292                 customclipplane = plane;
7293         }
7294
7295         if (!r_refdef.view.useperspective)
7296                 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);
7297         else if (vid.stencil && r_useinfinitefarclip.integer)
7298                 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);
7299         else
7300                 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);
7301         R_SetViewport(&r_refdef.view.viewport);
7302 }
7303
7304 void R_EntityMatrix(const matrix4x4_t *matrix)
7305 {
7306         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
7307         {
7308                 gl_modelmatrixchanged = false;
7309                 gl_modelmatrix = *matrix;
7310                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
7311                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
7312                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
7313                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
7314                 CHECKGLERROR
7315                 switch(vid.renderpath)
7316                 {
7317                 case RENDERPATH_GL20:
7318                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
7319                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
7320                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7321                         break;
7322                 case RENDERPATH_CGGL:
7323 #ifdef SUPPORTCG
7324                         CHECKCGERROR
7325                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
7326                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
7327                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7328 #endif
7329                         break;
7330                 case RENDERPATH_GL13:
7331                 case RENDERPATH_GL11:
7332                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7333                         break;
7334                 }
7335         }
7336 }
7337
7338 void R_ResetViewRendering2D(void)
7339 {
7340         r_viewport_t viewport;
7341         DrawQ_Finish();
7342
7343         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
7344         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);
7345         R_SetViewport(&viewport);
7346         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
7347         GL_Color(1, 1, 1, 1);
7348         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7349         GL_BlendFunc(GL_ONE, GL_ZERO);
7350         GL_AlphaTest(false);
7351         GL_ScissorTest(false);
7352         GL_DepthMask(false);
7353         GL_DepthRange(0, 1);
7354         GL_DepthTest(false);
7355         R_EntityMatrix(&identitymatrix);
7356         R_Mesh_ResetTextureState();
7357         GL_PolygonOffset(0, 0);
7358         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7359         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7360         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7361         qglStencilMask(~0);CHECKGLERROR
7362         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7363         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7364         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
7365 }
7366
7367 void R_ResetViewRendering3D(void)
7368 {
7369         DrawQ_Finish();
7370
7371         R_SetupView(true);
7372         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7373         GL_Color(1, 1, 1, 1);
7374         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7375         GL_BlendFunc(GL_ONE, GL_ZERO);
7376         GL_AlphaTest(false);
7377         GL_ScissorTest(true);
7378         GL_DepthMask(true);
7379         GL_DepthRange(0, 1);
7380         GL_DepthTest(true);
7381         R_EntityMatrix(&identitymatrix);
7382         R_Mesh_ResetTextureState();
7383         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7384         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7385         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7386         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7387         qglStencilMask(~0);CHECKGLERROR
7388         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7389         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7390         GL_CullFace(r_refdef.view.cullface_back);
7391 }
7392
7393 /*
7394 ================
7395 R_RenderView_UpdateViewVectors
7396 ================
7397 */
7398 static void R_RenderView_UpdateViewVectors(void)
7399 {
7400         // break apart the view matrix into vectors for various purposes
7401         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
7402         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
7403         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
7404         VectorNegate(r_refdef.view.left, r_refdef.view.right);
7405         // make an inverted copy of the view matrix for tracking sprites
7406         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
7407 }
7408
7409 void R_RenderScene(void);
7410 void R_RenderWaterPlanes(void);
7411
7412 static void R_Water_StartFrame(void)
7413 {
7414         int i;
7415         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
7416         r_waterstate_waterplane_t *p;
7417
7418         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
7419                 return;
7420
7421         switch(vid.renderpath)
7422         {
7423         case RENDERPATH_GL20:
7424         case RENDERPATH_CGGL:
7425                 break;
7426         case RENDERPATH_GL13:
7427         case RENDERPATH_GL11:
7428                 return;
7429         }
7430
7431         // set waterwidth and waterheight to the water resolution that will be
7432         // used (often less than the screen resolution for faster rendering)
7433         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
7434         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
7435
7436         // calculate desired texture sizes
7437         // can't use water if the card does not support the texture size
7438         if (!r_water.integer || r_showsurfaces.integer)
7439                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
7440         else if (vid.support.arb_texture_non_power_of_two)
7441         {
7442                 texturewidth = waterwidth;
7443                 textureheight = waterheight;
7444                 camerawidth = waterwidth;
7445                 cameraheight = waterheight;
7446         }
7447         else
7448         {
7449                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
7450                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
7451                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
7452                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
7453         }
7454
7455         // allocate textures as needed
7456         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
7457         {
7458                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7459                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
7460                 {
7461                         if (p->texture_refraction)
7462                                 R_FreeTexture(p->texture_refraction);
7463                         p->texture_refraction = NULL;
7464                         if (p->texture_reflection)
7465                                 R_FreeTexture(p->texture_reflection);
7466                         p->texture_reflection = NULL;
7467                         if (p->texture_camera)
7468                                 R_FreeTexture(p->texture_camera);
7469                         p->texture_camera = NULL;
7470                 }
7471                 memset(&r_waterstate, 0, sizeof(r_waterstate));
7472                 r_waterstate.texturewidth = texturewidth;
7473                 r_waterstate.textureheight = textureheight;
7474                 r_waterstate.camerawidth = camerawidth;
7475                 r_waterstate.cameraheight = cameraheight;
7476         }
7477
7478         if (r_waterstate.texturewidth)
7479         {
7480                 r_waterstate.enabled = true;
7481
7482                 // when doing a reduced render (HDR) we want to use a smaller area
7483                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
7484                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
7485
7486                 // set up variables that will be used in shader setup
7487                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7488                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7489                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7490                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7491         }
7492
7493         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7494         r_waterstate.numwaterplanes = 0;
7495 }
7496
7497 void R_Water_AddWaterPlane(msurface_t *surface)
7498 {
7499         int triangleindex, planeindex;
7500         const int *e;
7501         vec3_t vert[3];
7502         vec3_t normal;
7503         vec3_t center;
7504         mplane_t plane;
7505         int cam_ent;
7506         r_waterstate_waterplane_t *p;
7507         texture_t *t = R_GetCurrentTexture(surface->texture);
7508         cam_ent = t->camera_entity;
7509         if(!(t->currentmaterialflags & MATERIALFLAG_CAMERA))
7510                 cam_ent = 0;
7511
7512         // just use the first triangle with a valid normal for any decisions
7513         VectorClear(normal);
7514         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
7515         {
7516                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
7517                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
7518                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
7519                 TriangleNormal(vert[0], vert[1], vert[2], normal);
7520                 if (VectorLength2(normal) >= 0.001)
7521                         break;
7522         }
7523
7524         VectorCopy(normal, plane.normal);
7525         VectorNormalize(plane.normal);
7526         plane.dist = DotProduct(vert[0], plane.normal);
7527         PlaneClassify(&plane);
7528         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
7529         {
7530                 // skip backfaces (except if nocullface is set)
7531                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
7532                         return;
7533                 VectorNegate(plane.normal, plane.normal);
7534                 plane.dist *= -1;
7535                 PlaneClassify(&plane);
7536         }
7537
7538
7539         // find a matching plane if there is one
7540         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7541                 if(p->camera_entity == t->camera_entity)
7542                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
7543                                 break;
7544         if (planeindex >= r_waterstate.maxwaterplanes)
7545                 return; // nothing we can do, out of planes
7546
7547         // if this triangle does not fit any known plane rendered this frame, add one
7548         if (planeindex >= r_waterstate.numwaterplanes)
7549         {
7550                 // store the new plane
7551                 r_waterstate.numwaterplanes++;
7552                 p->plane = plane;
7553                 // clear materialflags and pvs
7554                 p->materialflags = 0;
7555                 p->pvsvalid = false;
7556                 p->camera_entity = t->camera_entity;
7557         }
7558         // merge this surface's materialflags into the waterplane
7559         p->materialflags |= t->currentmaterialflags;
7560         if(!(p->materialflags & MATERIALFLAG_CAMERA))
7561         {
7562                 // merge this surface's PVS into the waterplane
7563                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
7564                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
7565                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
7566                 {
7567                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
7568                         p->pvsvalid = true;
7569                 }
7570         }
7571 }
7572
7573 static void R_Water_ProcessPlanes(void)
7574 {
7575         r_refdef_view_t originalview;
7576         r_refdef_view_t myview;
7577         int planeindex;
7578         r_waterstate_waterplane_t *p;
7579         vec3_t visorigin;
7580
7581         originalview = r_refdef.view;
7582
7583         // make sure enough textures are allocated
7584         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7585         {
7586                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7587                 {
7588                         if (!p->texture_refraction)
7589                                 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);
7590                         if (!p->texture_refraction)
7591                                 goto error;
7592                 }
7593                 else if (p->materialflags & MATERIALFLAG_CAMERA)
7594                 {
7595                         if (!p->texture_camera)
7596                                 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_waterstate.camerawidth, r_waterstate.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR, NULL);
7597                         if (!p->texture_camera)
7598                                 goto error;
7599                 }
7600
7601                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7602                 {
7603                         if (!p->texture_reflection)
7604                                 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);
7605                         if (!p->texture_reflection)
7606                                 goto error;
7607                 }
7608         }
7609
7610         // render views
7611         r_refdef.view = originalview;
7612         r_refdef.view.showdebug = false;
7613         r_refdef.view.width = r_waterstate.waterwidth;
7614         r_refdef.view.height = r_waterstate.waterheight;
7615         r_refdef.view.useclipplane = true;
7616         myview = r_refdef.view;
7617         r_waterstate.renderingscene = true;
7618         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7619         {
7620                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7621                 {
7622                         r_refdef.view = myview;
7623                         // render reflected scene and copy into texture
7624                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
7625                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
7626                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
7627                         r_refdef.view.clipplane = p->plane;
7628                         // reverse the cullface settings for this render
7629                         r_refdef.view.cullface_front = GL_FRONT;
7630                         r_refdef.view.cullface_back = GL_BACK;
7631                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
7632                         {
7633                                 r_refdef.view.usecustompvs = true;
7634                                 if (p->pvsvalid)
7635                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7636                                 else
7637                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7638                         }
7639
7640                         R_ResetViewRendering3D();
7641                         R_ClearScreen(r_refdef.fogenabled);
7642                         R_View_Update();
7643                         R_RenderScene();
7644
7645                         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);
7646                 }
7647
7648                 // render the normal view scene and copy into texture
7649                 // (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)
7650                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7651                 {
7652                         r_waterstate.renderingrefraction = true;
7653                         r_refdef.view = myview;
7654
7655                         r_refdef.view.clipplane = p->plane;
7656                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
7657                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
7658
7659                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
7660                         {
7661                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
7662                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
7663                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
7664                                 R_RenderView_UpdateViewVectors();
7665                                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
7666                         }
7667
7668                         PlaneClassify(&r_refdef.view.clipplane);
7669
7670                         R_ResetViewRendering3D();
7671                         R_ClearScreen(r_refdef.fogenabled);
7672                         R_View_Update();
7673                         R_RenderScene();
7674
7675                         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);
7676                         r_waterstate.renderingrefraction = false;
7677                 }
7678                 else if (p->materialflags & MATERIALFLAG_CAMERA)
7679                 {
7680                         r_refdef.view = myview;
7681
7682                         r_refdef.view.clipplane = p->plane;
7683                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
7684                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
7685
7686                         r_refdef.view.width = r_waterstate.camerawidth;
7687                         r_refdef.view.height = r_waterstate.cameraheight;
7688                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
7689                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
7690
7691                         if(p->camera_entity)
7692                         {
7693                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
7694                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
7695                         }
7696
7697                         // reverse the cullface settings for this render
7698                         r_refdef.view.cullface_front = GL_FRONT;
7699                         r_refdef.view.cullface_back = GL_BACK;
7700                         // also reverse the view matrix
7701                         Matrix4x4_ConcatScale3(&r_refdef.view.matrix, 1, -1, 1);
7702                         R_RenderView_UpdateViewVectors();
7703                         if(p->camera_entity)
7704                                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
7705                         
7706                         // camera needs no clipplane
7707                         r_refdef.view.useclipplane = false;
7708
7709                         PlaneClassify(&r_refdef.view.clipplane);
7710
7711                         R_ResetViewRendering3D();
7712                         R_ClearScreen(r_refdef.fogenabled);
7713                         R_View_Update();
7714                         R_RenderScene();
7715
7716                         R_Mesh_CopyToTexture(p->texture_camera, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7717                         r_waterstate.renderingrefraction = false;
7718                 }
7719
7720         }
7721         r_waterstate.renderingscene = false;
7722         r_refdef.view = originalview;
7723         R_ResetViewRendering3D();
7724         R_ClearScreen(r_refdef.fogenabled);
7725         R_View_Update();
7726         return;
7727 error:
7728         r_refdef.view = originalview;
7729         r_waterstate.renderingscene = false;
7730         Cvar_SetValueQuick(&r_water, 0);
7731         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
7732         return;
7733 }
7734
7735 void R_Bloom_StartFrame(void)
7736 {
7737         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
7738
7739         switch(vid.renderpath)
7740         {
7741         case RENDERPATH_GL20:
7742         case RENDERPATH_CGGL:
7743                 break;
7744         case RENDERPATH_GL13:
7745         case RENDERPATH_GL11:
7746                 return;
7747         }
7748
7749         // set bloomwidth and bloomheight to the bloom resolution that will be
7750         // used (often less than the screen resolution for faster rendering)
7751         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
7752         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
7753         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
7754         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
7755         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
7756
7757         // calculate desired texture sizes
7758         if (vid.support.arb_texture_non_power_of_two)
7759         {
7760                 screentexturewidth = r_refdef.view.width;
7761                 screentextureheight = r_refdef.view.height;
7762                 bloomtexturewidth = r_bloomstate.bloomwidth;
7763                 bloomtextureheight = r_bloomstate.bloomheight;
7764         }
7765         else
7766         {
7767                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
7768                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
7769                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
7770                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
7771         }
7772
7773         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))
7774         {
7775                 Cvar_SetValueQuick(&r_hdr, 0);
7776                 Cvar_SetValueQuick(&r_bloom, 0);
7777                 Cvar_SetValueQuick(&r_motionblur, 0);
7778                 Cvar_SetValueQuick(&r_damageblur, 0);
7779         }
7780
7781         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)))
7782                 screentexturewidth = screentextureheight = 0;
7783         if (!r_hdr.integer && !r_bloom.integer)
7784                 bloomtexturewidth = bloomtextureheight = 0;
7785
7786         // allocate textures as needed
7787         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
7788         {
7789                 if (r_bloomstate.texture_screen)
7790                         R_FreeTexture(r_bloomstate.texture_screen);
7791                 r_bloomstate.texture_screen = NULL;
7792                 r_bloomstate.screentexturewidth = screentexturewidth;
7793                 r_bloomstate.screentextureheight = screentextureheight;
7794                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
7795                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
7796         }
7797         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
7798         {
7799                 if (r_bloomstate.texture_bloom)
7800                         R_FreeTexture(r_bloomstate.texture_bloom);
7801                 r_bloomstate.texture_bloom = NULL;
7802                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
7803                 r_bloomstate.bloomtextureheight = bloomtextureheight;
7804                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
7805                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7806         }
7807
7808         // when doing a reduced render (HDR) we want to use a smaller area
7809         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
7810         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
7811         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
7812         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
7813         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
7814
7815         // set up a texcoord array for the full resolution screen image
7816         // (we have to keep this around to copy back during final render)
7817         r_bloomstate.screentexcoord2f[0] = 0;
7818         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7819         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7820         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7821         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7822         r_bloomstate.screentexcoord2f[5] = 0;
7823         r_bloomstate.screentexcoord2f[6] = 0;
7824         r_bloomstate.screentexcoord2f[7] = 0;
7825
7826         // set up a texcoord array for the reduced resolution bloom image
7827         // (which will be additive blended over the screen image)
7828         r_bloomstate.bloomtexcoord2f[0] = 0;
7829         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7830         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7831         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7832         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7833         r_bloomstate.bloomtexcoord2f[5] = 0;
7834         r_bloomstate.bloomtexcoord2f[6] = 0;
7835         r_bloomstate.bloomtexcoord2f[7] = 0;
7836
7837         if (r_hdr.integer || r_bloom.integer)
7838         {
7839                 r_bloomstate.enabled = true;
7840                 r_bloomstate.hdr = r_hdr.integer != 0;
7841         }
7842
7843         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);
7844 }
7845
7846 void R_Bloom_CopyBloomTexture(float colorscale)
7847 {
7848         r_refdef.stats.bloom++;
7849
7850         // scale down screen texture to the bloom texture size
7851         CHECKGLERROR
7852         R_SetViewport(&r_bloomstate.viewport);
7853         GL_BlendFunc(GL_ONE, GL_ZERO);
7854         GL_Color(colorscale, colorscale, colorscale, 1);
7855         // TODO: optimize with multitexture or GLSL
7856         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7857         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7858         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7859         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7860
7861         // we now have a bloom image in the framebuffer
7862         // copy it into the bloom image texture for later processing
7863         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);
7864         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7865 }
7866
7867 void R_Bloom_CopyHDRTexture(void)
7868 {
7869         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);
7870         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7871 }
7872
7873 void R_Bloom_MakeTexture(void)
7874 {
7875         int x, range, dir;
7876         float xoffset, yoffset, r, brighten;
7877
7878         r_refdef.stats.bloom++;
7879
7880         R_ResetViewRendering2D();
7881         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7882         R_Mesh_ColorPointer(NULL, 0, 0);
7883
7884         // we have a bloom image in the framebuffer
7885         CHECKGLERROR
7886         R_SetViewport(&r_bloomstate.viewport);
7887
7888         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
7889         {
7890                 x *= 2;
7891                 r = bound(0, r_bloom_colorexponent.value / x, 1);
7892                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7893                 GL_Color(r, r, r, 1);
7894                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7895                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7896                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7897                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7898
7899                 // copy the vertically blurred bloom view to a texture
7900                 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);
7901                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7902         }
7903
7904         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
7905         brighten = r_bloom_brighten.value;
7906         if (r_hdr.integer)
7907                 brighten *= r_hdr_range.value;
7908         brighten = sqrt(brighten);
7909         if(range >= 1)
7910                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
7911         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7912         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
7913
7914         for (dir = 0;dir < 2;dir++)
7915         {
7916                 // blend on at multiple vertical offsets to achieve a vertical blur
7917                 // TODO: do offset blends using GLSL
7918                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
7919                 GL_BlendFunc(GL_ONE, GL_ZERO);
7920                 for (x = -range;x <= range;x++)
7921                 {
7922                         if (!dir){xoffset = 0;yoffset = x;}
7923                         else {xoffset = x;yoffset = 0;}
7924                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
7925                         yoffset /= (float)r_bloomstate.bloomtextureheight;
7926                         // compute a texcoord array with the specified x and y offset
7927                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
7928                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7929                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7930                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7931                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7932                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
7933                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
7934                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
7935                         // this r value looks like a 'dot' particle, fading sharply to
7936                         // black at the edges
7937                         // (probably not realistic but looks good enough)
7938                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
7939                         //r = brighten/(range*2+1);
7940                         r = brighten / (range * 2 + 1);
7941                         if(range >= 1)
7942                                 r *= (1 - x*x/(float)(range*range));
7943                         GL_Color(r, r, r, 1);
7944                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7945                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7946                         GL_BlendFunc(GL_ONE, GL_ONE);
7947                 }
7948
7949                 // copy the vertically blurred bloom view to a texture
7950                 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);
7951                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7952         }
7953
7954         // apply subtract last
7955         // (just like it would be in a GLSL shader)
7956         if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
7957         {
7958                 GL_BlendFunc(GL_ONE, GL_ZERO);
7959                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7960                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7961                 GL_Color(1, 1, 1, 1);
7962                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7963                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7964
7965                 GL_BlendFunc(GL_ONE, GL_ONE);
7966                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
7967                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7968                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7969                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
7970                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7971                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7972                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
7973
7974                 // copy the darkened bloom view to a texture
7975                 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);
7976                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7977         }
7978 }
7979
7980 void R_HDR_RenderBloomTexture(void)
7981 {
7982         int oldwidth, oldheight;
7983         float oldcolorscale;
7984
7985         oldcolorscale = r_refdef.view.colorscale;
7986         oldwidth = r_refdef.view.width;
7987         oldheight = r_refdef.view.height;
7988         r_refdef.view.width = r_bloomstate.bloomwidth;
7989         r_refdef.view.height = r_bloomstate.bloomheight;
7990
7991         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
7992         // TODO: add exposure compensation features
7993         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
7994
7995         r_refdef.view.showdebug = false;
7996         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
7997
7998         R_ResetViewRendering3D();
7999
8000         R_ClearScreen(r_refdef.fogenabled);
8001         if (r_timereport_active)
8002                 R_TimeReport("HDRclear");
8003
8004         R_View_Update();
8005         if (r_timereport_active)
8006                 R_TimeReport("visibility");
8007
8008         // only do secondary renders with HDR if r_hdr is 2 or higher
8009         r_waterstate.numwaterplanes = 0;
8010         if (r_waterstate.enabled && r_hdr.integer >= 2)
8011                 R_RenderWaterPlanes();
8012
8013         r_refdef.view.showdebug = true;
8014         R_RenderScene();
8015         r_waterstate.numwaterplanes = 0;
8016
8017         R_ResetViewRendering2D();
8018
8019         R_Bloom_CopyHDRTexture();
8020         R_Bloom_MakeTexture();
8021
8022         // restore the view settings
8023         r_refdef.view.width = oldwidth;
8024         r_refdef.view.height = oldheight;
8025         r_refdef.view.colorscale = oldcolorscale;
8026
8027         R_ResetViewRendering3D();
8028
8029         R_ClearScreen(r_refdef.fogenabled);
8030         if (r_timereport_active)
8031                 R_TimeReport("viewclear");
8032 }
8033
8034 static void R_BlendView(void)
8035 {
8036         unsigned int permutation;
8037         float uservecs[4][4];
8038
8039         switch (vid.renderpath)
8040         {
8041         case RENDERPATH_GL20:
8042         case RENDERPATH_CGGL:
8043                 permutation =
8044                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
8045                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
8046                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
8047                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
8048                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
8049
8050                 if (r_bloomstate.texture_screen)
8051                 {
8052                         // make sure the buffer is available
8053                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
8054
8055                         R_ResetViewRendering2D();
8056                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
8057                         R_Mesh_ColorPointer(NULL, 0, 0);
8058
8059                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
8060                         {
8061                                 // declare variables
8062                                 float speed;
8063                                 static float avgspeed;
8064
8065                                 speed = VectorLength(cl.movement_velocity);
8066
8067                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
8068                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
8069
8070                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
8071                                 speed = bound(0, speed, 1);
8072                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
8073
8074                                 // calculate values into a standard alpha
8075                                 cl.motionbluralpha = 1 - exp(-
8076                                                 (
8077                                                  (r_motionblur.value * speed / 80)
8078                                                  +
8079                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
8080                                                 )
8081                                                 /
8082                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
8083                                            );
8084
8085                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
8086                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
8087                                 // apply the blur
8088                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
8089                                 {
8090                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8091                                         GL_Color(1, 1, 1, cl.motionbluralpha);
8092                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8093                                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
8094                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8095                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8096                                 }
8097                         }
8098
8099                         // copy view into the screen texture
8100                         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);
8101                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8102                 }
8103                 else if (!r_bloomstate.texture_bloom)
8104                 {
8105                         // we may still have to do view tint...
8106                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8107                         {
8108                                 // apply a color tint to the whole view
8109                                 R_ResetViewRendering2D();
8110                                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
8111                                 R_Mesh_ColorPointer(NULL, 0, 0);
8112                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8113                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8114                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8115                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8116                         }
8117                         break; // no screen processing, no bloom, skip it
8118                 }
8119
8120                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
8121                 {
8122                         // render simple bloom effect
8123                         // copy the screen and shrink it and darken it for the bloom process
8124                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
8125                         // make the bloom texture
8126                         R_Bloom_MakeTexture();
8127                 }
8128
8129 #if _MSC_VER >= 1400
8130 #define sscanf sscanf_s
8131 #endif
8132                 memset(uservecs, 0, sizeof(uservecs));
8133                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
8134                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
8135                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
8136                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
8137
8138                 R_ResetViewRendering2D();
8139                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
8140                 R_Mesh_ColorPointer(NULL, 0, 0);
8141                 GL_Color(1, 1, 1, 1);
8142                 GL_BlendFunc(GL_ONE, GL_ZERO);
8143                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
8144                 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
8145
8146                 switch(vid.renderpath)
8147                 {
8148                 case RENDERPATH_GL20:
8149                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
8150                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
8151                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
8152                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
8153                         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]);
8154                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8155                         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]);
8156                         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]);
8157                         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]);
8158                         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]);
8159                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
8160                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
8161                         break;
8162                 case RENDERPATH_CGGL:
8163 #ifdef SUPPORTCG
8164                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
8165                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
8166                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
8167                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
8168                         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
8169                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
8170                         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
8171                         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
8172                         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
8173                         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
8174                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
8175                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
8176 #endif
8177                         break;
8178                 default:
8179                         break;
8180                 }
8181                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8182                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8183                 break;
8184         case RENDERPATH_GL13:
8185         case RENDERPATH_GL11:
8186                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8187                 {
8188                         // apply a color tint to the whole view
8189                         R_ResetViewRendering2D();
8190                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
8191                         R_Mesh_ColorPointer(NULL, 0, 0);
8192                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8193                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8194                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8195                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8196                 }
8197                 break;
8198         }
8199 }
8200
8201 matrix4x4_t r_waterscrollmatrix;
8202
8203 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
8204 {
8205         if (r_refdef.fog_density)
8206         {
8207                 r_refdef.fogcolor[0] = r_refdef.fog_red;
8208                 r_refdef.fogcolor[1] = r_refdef.fog_green;
8209                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
8210
8211                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
8212                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
8213                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
8214                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
8215
8216                 {
8217                         vec3_t fogvec;
8218                         VectorCopy(r_refdef.fogcolor, fogvec);
8219                         //   color.rgb *= ContrastBoost * SceneBrightness;
8220                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
8221                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
8222                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
8223                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
8224                 }
8225         }
8226 }
8227
8228 void R_UpdateVariables(void)
8229 {
8230         R_Textures_Frame();
8231
8232         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
8233
8234         r_refdef.farclip = r_farclip_base.value;
8235         if (r_refdef.scene.worldmodel)
8236                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
8237         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
8238
8239         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
8240                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
8241         r_refdef.polygonfactor = 0;
8242         r_refdef.polygonoffset = 0;
8243         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8244         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8245
8246         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
8247         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
8248         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
8249         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
8250         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
8251         if (r_showsurfaces.integer)
8252         {
8253                 r_refdef.scene.rtworld = false;
8254                 r_refdef.scene.rtworldshadows = false;
8255                 r_refdef.scene.rtdlight = false;
8256                 r_refdef.scene.rtdlightshadows = false;
8257                 r_refdef.lightmapintensity = 0;
8258         }
8259
8260         if (gamemode == GAME_NEHAHRA)
8261         {
8262                 if (gl_fogenable.integer)
8263                 {
8264                         r_refdef.oldgl_fogenable = true;
8265                         r_refdef.fog_density = gl_fogdensity.value;
8266                         r_refdef.fog_red = gl_fogred.value;
8267                         r_refdef.fog_green = gl_foggreen.value;
8268                         r_refdef.fog_blue = gl_fogblue.value;
8269                         r_refdef.fog_alpha = 1;
8270                         r_refdef.fog_start = 0;
8271                         r_refdef.fog_end = gl_skyclip.value;
8272                         r_refdef.fog_height = 1<<30;
8273                         r_refdef.fog_fadedepth = 128;
8274                 }
8275                 else if (r_refdef.oldgl_fogenable)
8276                 {
8277                         r_refdef.oldgl_fogenable = false;
8278                         r_refdef.fog_density = 0;
8279                         r_refdef.fog_red = 0;
8280                         r_refdef.fog_green = 0;
8281                         r_refdef.fog_blue = 0;
8282                         r_refdef.fog_alpha = 0;
8283                         r_refdef.fog_start = 0;
8284                         r_refdef.fog_end = 0;
8285                         r_refdef.fog_height = 1<<30;
8286                         r_refdef.fog_fadedepth = 128;
8287                 }
8288         }
8289
8290         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
8291         r_refdef.fog_start = max(0, r_refdef.fog_start);
8292         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
8293
8294         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
8295
8296         if (r_refdef.fog_density && r_drawfog.integer)
8297         {
8298                 r_refdef.fogenabled = true;
8299                 // this is the point where the fog reaches 0.9986 alpha, which we
8300                 // consider a good enough cutoff point for the texture
8301                 // (0.9986 * 256 == 255.6)
8302                 if (r_fog_exp2.integer)
8303                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
8304                 else
8305                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
8306                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
8307                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
8308                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
8309                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
8310                         R_BuildFogHeightTexture();
8311                 // fog color was already set
8312                 // update the fog texture
8313                 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)
8314                         R_BuildFogTexture();
8315                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
8316                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
8317         }
8318         else
8319                 r_refdef.fogenabled = false;
8320
8321         switch(vid.renderpath)
8322         {
8323         case RENDERPATH_GL20:
8324         case RENDERPATH_CGGL:
8325                 if(v_glslgamma.integer && !vid_gammatables_trivial)
8326                 {
8327                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
8328                         {
8329                                 // build GLSL gamma texture
8330 #define RAMPWIDTH 256
8331                                 unsigned short ramp[RAMPWIDTH * 3];
8332                                 unsigned char rampbgr[RAMPWIDTH][4];
8333                                 int i;
8334
8335                                 r_texture_gammaramps_serial = vid_gammatables_serial;
8336
8337                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
8338                                 for(i = 0; i < RAMPWIDTH; ++i)
8339                                 {
8340                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8341                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8342                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
8343                                         rampbgr[i][3] = 0;
8344                                 }
8345                                 if (r_texture_gammaramps)
8346                                 {
8347                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
8348                                 }
8349                                 else
8350                                 {
8351                                         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);
8352                                 }
8353                         }
8354                 }
8355                 else
8356                 {
8357                         // remove GLSL gamma texture
8358                 }
8359                 break;
8360         case RENDERPATH_GL13:
8361         case RENDERPATH_GL11:
8362                 break;
8363         }
8364 }
8365
8366 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
8367 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
8368 /*
8369 ================
8370 R_SelectScene
8371 ================
8372 */
8373 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
8374         if( scenetype != r_currentscenetype ) {
8375                 // store the old scenetype
8376                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
8377                 r_currentscenetype = scenetype;
8378                 // move in the new scene
8379                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
8380         }
8381 }
8382
8383 /*
8384 ================
8385 R_GetScenePointer
8386 ================
8387 */
8388 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
8389 {
8390         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
8391         if( scenetype == r_currentscenetype ) {
8392                 return &r_refdef.scene;
8393         } else {
8394                 return &r_scenes_store[ scenetype ];
8395         }
8396 }
8397
8398 /*
8399 ================
8400 R_RenderView
8401 ================
8402 */
8403 void R_RenderView(void)
8404 {
8405         if (r_timereport_active)
8406                 R_TimeReport("start");
8407         r_textureframe++; // used only by R_GetCurrentTexture
8408         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8409
8410         if (!r_drawentities.integer)
8411                 r_refdef.scene.numentities = 0;
8412
8413         R_AnimCache_ClearCache();
8414         R_FrameData_NewFrame();
8415
8416         if (r_refdef.view.isoverlay)
8417         {
8418                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
8419                 GL_Clear( GL_DEPTH_BUFFER_BIT );
8420                 R_TimeReport("depthclear");
8421
8422                 r_refdef.view.showdebug = false;
8423
8424                 r_waterstate.enabled = false;
8425                 r_waterstate.numwaterplanes = 0;
8426
8427                 R_RenderScene();
8428
8429                 CHECKGLERROR
8430                 return;
8431         }
8432
8433         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
8434                 return; //Host_Error ("R_RenderView: NULL worldmodel");
8435
8436         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
8437
8438         R_RenderView_UpdateViewVectors();
8439
8440         R_Shadow_UpdateWorldLightSelection();
8441
8442         R_Bloom_StartFrame();
8443         R_Water_StartFrame();
8444
8445         CHECKGLERROR
8446         if (r_timereport_active)
8447                 R_TimeReport("viewsetup");
8448
8449         R_ResetViewRendering3D();
8450
8451         if (r_refdef.view.clear || r_refdef.fogenabled)
8452         {
8453                 R_ClearScreen(r_refdef.fogenabled);
8454                 if (r_timereport_active)
8455                         R_TimeReport("viewclear");
8456         }
8457         r_refdef.view.clear = true;
8458
8459         // this produces a bloom texture to be used in R_BlendView() later
8460         if (r_hdr.integer && r_bloomstate.bloomwidth)
8461         {
8462                 R_HDR_RenderBloomTexture();
8463                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
8464                 r_textureframe++; // used only by R_GetCurrentTexture
8465         }
8466
8467         r_refdef.view.showdebug = true;
8468
8469         R_View_Update();
8470         if (r_timereport_active)
8471                 R_TimeReport("visibility");
8472
8473         r_waterstate.numwaterplanes = 0;
8474         if (r_waterstate.enabled)
8475                 R_RenderWaterPlanes();
8476
8477         R_RenderScene();
8478         r_waterstate.numwaterplanes = 0;
8479
8480         R_BlendView();
8481         if (r_timereport_active)
8482                 R_TimeReport("blendview");
8483
8484         GL_Scissor(0, 0, vid.width, vid.height);
8485         GL_ScissorTest(false);
8486         CHECKGLERROR
8487 }
8488
8489 void R_RenderWaterPlanes(void)
8490 {
8491         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
8492         {
8493                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
8494                 if (r_timereport_active)
8495                         R_TimeReport("waterworld");
8496         }
8497
8498         // don't let sound skip if going slow
8499         if (r_refdef.scene.extraupdate)
8500                 S_ExtraUpdate ();
8501
8502         R_DrawModelsAddWaterPlanes();
8503         if (r_timereport_active)
8504                 R_TimeReport("watermodels");
8505
8506         if (r_waterstate.numwaterplanes)
8507         {
8508                 R_Water_ProcessPlanes();
8509                 if (r_timereport_active)
8510                         R_TimeReport("waterscenes");
8511         }
8512 }
8513
8514 extern void R_DrawLightningBeams (void);
8515 extern void VM_CL_AddPolygonsToMeshQueue (void);
8516 extern void R_DrawPortals (void);
8517 extern cvar_t cl_locs_show;
8518 static void R_DrawLocs(void);
8519 static void R_DrawEntityBBoxes(void);
8520 static void R_DrawModelDecals(void);
8521 extern void R_DrawModelShadows(void);
8522 extern void R_DrawModelShadowMaps(void);
8523 extern cvar_t cl_decals_newsystem;
8524 extern qboolean r_shadow_usingdeferredprepass;
8525 void R_RenderScene(void)
8526 {
8527         qboolean shadowmapping = false;
8528
8529         if (r_timereport_active)
8530                 R_TimeReport("beginscene");
8531
8532         r_refdef.stats.renders++;
8533
8534         R_UpdateFogColor();
8535
8536         // don't let sound skip if going slow
8537         if (r_refdef.scene.extraupdate)
8538                 S_ExtraUpdate ();
8539
8540         R_MeshQueue_BeginScene();
8541
8542         R_SkyStartFrame();
8543
8544         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);
8545
8546         if (r_timereport_active)
8547                 R_TimeReport("skystartframe");
8548
8549         if (cl.csqc_vidvars.drawworld)
8550         {
8551                 // don't let sound skip if going slow
8552                 if (r_refdef.scene.extraupdate)
8553                         S_ExtraUpdate ();
8554
8555                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
8556                 {
8557                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
8558                         if (r_timereport_active)
8559                                 R_TimeReport("worldsky");
8560                 }
8561
8562                 if (R_DrawBrushModelsSky() && r_timereport_active)
8563                         R_TimeReport("bmodelsky");
8564
8565                 if (skyrendermasked && skyrenderlater)
8566                 {
8567                         // we have to force off the water clipping plane while rendering sky
8568                         R_SetupView(false);
8569                         R_Sky();
8570                         R_SetupView(true);
8571                         if (r_timereport_active)
8572                                 R_TimeReport("sky");
8573                 }
8574         }
8575
8576         R_AnimCache_CacheVisibleEntities();
8577         if (r_timereport_active)
8578                 R_TimeReport("animation");
8579
8580         R_Shadow_PrepareLights();
8581         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
8582                 R_Shadow_PrepareModelShadows();
8583         if (r_timereport_active)
8584                 R_TimeReport("preparelights");
8585
8586         if (R_Shadow_ShadowMappingEnabled())
8587                 shadowmapping = true;
8588
8589         if (r_shadow_usingdeferredprepass)
8590                 R_Shadow_DrawPrepass();
8591
8592         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
8593         {
8594                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
8595                 if (r_timereport_active)
8596                         R_TimeReport("worlddepth");
8597         }
8598         if (r_depthfirst.integer >= 2)
8599         {
8600                 R_DrawModelsDepth();
8601                 if (r_timereport_active)
8602                         R_TimeReport("modeldepth");
8603         }
8604
8605         if (r_shadows.integer > 0 && shadowmapping && r_refdef.lightmapintensity > 0)
8606         {
8607                 R_DrawModelShadowMaps();
8608                 R_ResetViewRendering3D();
8609                 // don't let sound skip if going slow
8610                 if (r_refdef.scene.extraupdate)
8611                         S_ExtraUpdate ();
8612         }
8613
8614         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
8615         {
8616                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
8617                 if (r_timereport_active)
8618                         R_TimeReport("world");
8619         }
8620
8621         // don't let sound skip if going slow
8622         if (r_refdef.scene.extraupdate)
8623                 S_ExtraUpdate ();
8624
8625         R_DrawModels();
8626         if (r_timereport_active)
8627                 R_TimeReport("models");
8628
8629         // don't let sound skip if going slow
8630         if (r_refdef.scene.extraupdate)
8631                 S_ExtraUpdate ();
8632
8633         if (r_shadows.integer > 0 && !shadowmapping && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8634         {
8635                 R_DrawModelShadows();
8636                 R_ResetViewRendering3D();
8637                 // don't let sound skip if going slow
8638                 if (r_refdef.scene.extraupdate)
8639                         S_ExtraUpdate ();
8640         }
8641
8642         if (!r_shadow_usingdeferredprepass)
8643         {
8644                 R_Shadow_DrawLights();
8645                 if (r_timereport_active)
8646                         R_TimeReport("rtlights");
8647         }
8648
8649         // don't let sound skip if going slow
8650         if (r_refdef.scene.extraupdate)
8651                 S_ExtraUpdate ();
8652
8653         if (r_shadows.integer > 0 && !shadowmapping && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8654         {
8655                 R_DrawModelShadows();
8656                 R_ResetViewRendering3D();
8657                 // don't let sound skip if going slow
8658                 if (r_refdef.scene.extraupdate)
8659                         S_ExtraUpdate ();
8660         }
8661
8662         if (cl.csqc_vidvars.drawworld)
8663         {
8664                 if (cl_decals_newsystem.integer)
8665                 {
8666                         R_DrawModelDecals();
8667                         if (r_timereport_active)
8668                                 R_TimeReport("modeldecals");
8669                 }
8670                 else
8671                 {
8672                         R_DrawDecals();
8673                         if (r_timereport_active)
8674                                 R_TimeReport("decals");
8675                 }
8676
8677                 R_DrawParticles();
8678                 if (r_timereport_active)
8679                         R_TimeReport("particles");
8680
8681                 R_DrawExplosions();
8682                 if (r_timereport_active)
8683                         R_TimeReport("explosions");
8684
8685                 R_DrawLightningBeams();
8686                 if (r_timereport_active)
8687                         R_TimeReport("lightning");
8688         }
8689
8690         VM_CL_AddPolygonsToMeshQueue();
8691
8692         if (r_refdef.view.showdebug)
8693         {
8694                 if (cl_locs_show.integer)
8695                 {
8696                         R_DrawLocs();
8697                         if (r_timereport_active)
8698                                 R_TimeReport("showlocs");
8699                 }
8700
8701                 if (r_drawportals.integer)
8702                 {
8703                         R_DrawPortals();
8704                         if (r_timereport_active)
8705                                 R_TimeReport("portals");
8706                 }
8707
8708                 if (r_showbboxes.value > 0)
8709                 {
8710                         R_DrawEntityBBoxes();
8711                         if (r_timereport_active)
8712                                 R_TimeReport("bboxes");
8713                 }
8714         }
8715
8716         R_MeshQueue_RenderTransparent();
8717         if (r_timereport_active)
8718                 R_TimeReport("drawtrans");
8719
8720         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))
8721         {
8722                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
8723                 if (r_timereport_active)
8724                         R_TimeReport("worlddebug");
8725                 R_DrawModelsDebug();
8726                 if (r_timereport_active)
8727                         R_TimeReport("modeldebug");
8728         }
8729
8730         if (cl.csqc_vidvars.drawworld)
8731         {
8732                 R_Shadow_DrawCoronas();
8733                 if (r_timereport_active)
8734                         R_TimeReport("coronas");
8735         }
8736
8737         // don't let sound skip if going slow
8738         if (r_refdef.scene.extraupdate)
8739                 S_ExtraUpdate ();
8740
8741         R_ResetViewRendering2D();
8742 }
8743
8744 static const unsigned short bboxelements[36] =
8745 {
8746         5, 1, 3, 5, 3, 7,
8747         6, 2, 0, 6, 0, 4,
8748         7, 3, 2, 7, 2, 6,
8749         4, 0, 1, 4, 1, 5,
8750         4, 5, 7, 4, 7, 6,
8751         1, 0, 2, 1, 2, 3,
8752 };
8753
8754 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
8755 {
8756         int i;
8757         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
8758
8759         RSurf_ActiveWorldEntity();
8760
8761         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8762         GL_DepthMask(false);
8763         GL_DepthRange(0, 1);
8764         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8765         R_Mesh_ResetTextureState();
8766
8767         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
8768         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
8769         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
8770         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
8771         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
8772         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
8773         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
8774         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
8775         R_FillColors(color4f, 8, cr, cg, cb, ca);
8776         if (r_refdef.fogenabled)
8777         {
8778                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
8779                 {
8780                         f1 = RSurf_FogVertex(v);
8781                         f2 = 1 - f1;
8782                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
8783                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
8784                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
8785                 }
8786         }
8787         R_Mesh_VertexPointer(vertex3f, 0, 0);
8788         R_Mesh_ColorPointer(color4f, 0, 0);
8789         R_Mesh_ResetTextureState();
8790         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8791         R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
8792 }
8793
8794 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8795 {
8796         int i;
8797         float color[4];
8798         prvm_edict_t *edict;
8799         prvm_prog_t *prog_save = prog;
8800
8801         // this function draws bounding boxes of server entities
8802         if (!sv.active)
8803                 return;
8804
8805         GL_CullFace(GL_NONE);
8806         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8807
8808         prog = 0;
8809         SV_VM_Begin();
8810         for (i = 0;i < numsurfaces;i++)
8811         {
8812                 edict = PRVM_EDICT_NUM(surfacelist[i]);
8813                 switch ((int)edict->fields.server->solid)
8814                 {
8815                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
8816                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
8817                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
8818                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
8819                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
8820                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
8821                 }
8822                 color[3] *= r_showbboxes.value;
8823                 color[3] = bound(0, color[3], 1);
8824                 GL_DepthTest(!r_showdisabledepthtest.integer);
8825                 GL_CullFace(r_refdef.view.cullface_front);
8826                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
8827         }
8828         SV_VM_End();
8829         prog = prog_save;
8830 }
8831
8832 static void R_DrawEntityBBoxes(void)
8833 {
8834         int i;
8835         prvm_edict_t *edict;
8836         vec3_t center;
8837         prvm_prog_t *prog_save = prog;
8838
8839         // this function draws bounding boxes of server entities
8840         if (!sv.active)
8841                 return;
8842
8843         prog = 0;
8844         SV_VM_Begin();
8845         for (i = 0;i < prog->num_edicts;i++)
8846         {
8847                 edict = PRVM_EDICT_NUM(i);
8848                 if (edict->priv.server->free)
8849                         continue;
8850                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
8851                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
8852                         continue;
8853                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
8854                         continue;
8855                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
8856                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
8857         }
8858         SV_VM_End();
8859         prog = prog_save;
8860 }
8861
8862 static const int nomodelelement3i[24] =
8863 {
8864         5, 2, 0,
8865         5, 1, 2,
8866         5, 0, 3,
8867         5, 3, 1,
8868         0, 2, 4,
8869         2, 1, 4,
8870         3, 0, 4,
8871         1, 3, 4
8872 };
8873
8874 static const unsigned short nomodelelement3s[24] =
8875 {
8876         5, 2, 0,
8877         5, 1, 2,
8878         5, 0, 3,
8879         5, 3, 1,
8880         0, 2, 4,
8881         2, 1, 4,
8882         3, 0, 4,
8883         1, 3, 4
8884 };
8885
8886 static const float nomodelvertex3f[6*3] =
8887 {
8888         -16,   0,   0,
8889          16,   0,   0,
8890           0, -16,   0,
8891           0,  16,   0,
8892           0,   0, -16,
8893           0,   0,  16
8894 };
8895
8896 static const float nomodelcolor4f[6*4] =
8897 {
8898         0.0f, 0.0f, 0.5f, 1.0f,
8899         0.0f, 0.0f, 0.5f, 1.0f,
8900         0.0f, 0.5f, 0.0f, 1.0f,
8901         0.0f, 0.5f, 0.0f, 1.0f,
8902         0.5f, 0.0f, 0.0f, 1.0f,
8903         0.5f, 0.0f, 0.0f, 1.0f
8904 };
8905
8906 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8907 {
8908         int i;
8909         float f1, f2, *c;
8910         float color4f[6*4];
8911
8912         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);
8913
8914         // this is only called once per entity so numsurfaces is always 1, and
8915         // surfacelist is always {0}, so this code does not handle batches
8916
8917         if (rsurface.ent_flags & RENDER_ADDITIVE)
8918         {
8919                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
8920                 GL_DepthMask(false);
8921         }
8922         else if (rsurface.colormod[3] < 1)
8923         {
8924                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8925                 GL_DepthMask(false);
8926         }
8927         else
8928         {
8929                 GL_BlendFunc(GL_ONE, GL_ZERO);
8930                 GL_DepthMask(true);
8931         }
8932         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8933         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8934         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8935         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8936         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8937         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
8938         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8939         R_Mesh_ColorPointer(color4f, 0, 0);
8940         for (i = 0, c = color4f;i < 6;i++, c += 4)
8941         {
8942                 c[0] *= rsurface.colormod[0];
8943                 c[1] *= rsurface.colormod[1];
8944                 c[2] *= rsurface.colormod[2];
8945                 c[3] *= rsurface.colormod[3];
8946         }
8947         if (r_refdef.fogenabled)
8948         {
8949                 for (i = 0, c = color4f;i < 6;i++, c += 4)
8950                 {
8951                         f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
8952                         f2 = 1 - f1;
8953                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8954                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8955                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8956                 }
8957         }
8958         R_Mesh_ResetTextureState();
8959         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
8960 }
8961
8962 void R_DrawNoModel(entity_render_t *ent)
8963 {
8964         vec3_t org;
8965         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8966         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8967                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8968         else
8969                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8970 }
8971
8972 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8973 {
8974         vec3_t right1, right2, diff, normal;
8975
8976         VectorSubtract (org2, org1, normal);
8977
8978         // calculate 'right' vector for start
8979         VectorSubtract (r_refdef.view.origin, org1, diff);
8980         CrossProduct (normal, diff, right1);
8981         VectorNormalize (right1);
8982
8983         // calculate 'right' vector for end
8984         VectorSubtract (r_refdef.view.origin, org2, diff);
8985         CrossProduct (normal, diff, right2);
8986         VectorNormalize (right2);
8987
8988         vert[ 0] = org1[0] + width * right1[0];
8989         vert[ 1] = org1[1] + width * right1[1];
8990         vert[ 2] = org1[2] + width * right1[2];
8991         vert[ 3] = org1[0] - width * right1[0];
8992         vert[ 4] = org1[1] - width * right1[1];
8993         vert[ 5] = org1[2] - width * right1[2];
8994         vert[ 6] = org2[0] - width * right2[0];
8995         vert[ 7] = org2[1] - width * right2[1];
8996         vert[ 8] = org2[2] - width * right2[2];
8997         vert[ 9] = org2[0] + width * right2[0];
8998         vert[10] = org2[1] + width * right2[1];
8999         vert[11] = org2[2] + width * right2[2];
9000 }
9001
9002 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)
9003 {
9004         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
9005         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
9006         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
9007         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
9008         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
9009         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
9010         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
9011         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
9012         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
9013         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
9014         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
9015         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
9016 }
9017
9018 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
9019 {
9020         int i;
9021         float *vertex3f;
9022         float v[3];
9023         VectorSet(v, x, y, z);
9024         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
9025                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
9026                         break;
9027         if (i == mesh->numvertices)
9028         {
9029                 if (mesh->numvertices < mesh->maxvertices)
9030                 {
9031                         VectorCopy(v, vertex3f);
9032                         mesh->numvertices++;
9033                 }
9034                 return mesh->numvertices;
9035         }
9036         else
9037                 return i;
9038 }
9039
9040 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
9041 {
9042         int i;
9043         int *e, element[3];
9044         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9045         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9046         e = mesh->element3i + mesh->numtriangles * 3;
9047         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
9048         {
9049                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
9050                 if (mesh->numtriangles < mesh->maxtriangles)
9051                 {
9052                         *e++ = element[0];
9053                         *e++ = element[1];
9054                         *e++ = element[2];
9055                         mesh->numtriangles++;
9056                 }
9057                 element[1] = element[2];
9058         }
9059 }
9060
9061 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
9062 {
9063         int i;
9064         int *e, element[3];
9065         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9066         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9067         e = mesh->element3i + mesh->numtriangles * 3;
9068         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
9069         {
9070                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
9071                 if (mesh->numtriangles < mesh->maxtriangles)
9072                 {
9073                         *e++ = element[0];
9074                         *e++ = element[1];
9075                         *e++ = element[2];
9076                         mesh->numtriangles++;
9077                 }
9078                 element[1] = element[2];
9079         }
9080 }
9081
9082 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
9083 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
9084 {
9085         int planenum, planenum2;
9086         int w;
9087         int tempnumpoints;
9088         mplane_t *plane, *plane2;
9089         double maxdist;
9090         double temppoints[2][256*3];
9091         // figure out how large a bounding box we need to properly compute this brush
9092         maxdist = 0;
9093         for (w = 0;w < numplanes;w++)
9094                 maxdist = max(maxdist, fabs(planes[w].dist));
9095         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
9096         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
9097         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
9098         {
9099                 w = 0;
9100                 tempnumpoints = 4;
9101                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
9102                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
9103                 {
9104                         if (planenum2 == planenum)
9105                                 continue;
9106                         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);
9107                         w = !w;
9108                 }
9109                 if (tempnumpoints < 3)
9110                         continue;
9111                 // generate elements forming a triangle fan for this polygon
9112                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
9113         }
9114 }
9115
9116 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)
9117 {
9118         texturelayer_t *layer;
9119         layer = t->currentlayers + t->currentnumlayers++;
9120         layer->type = type;
9121         layer->depthmask = depthmask;
9122         layer->blendfunc1 = blendfunc1;
9123         layer->blendfunc2 = blendfunc2;
9124         layer->texture = texture;
9125         layer->texmatrix = *matrix;
9126         layer->color[0] = r;
9127         layer->color[1] = g;
9128         layer->color[2] = b;
9129         layer->color[3] = a;
9130 }
9131
9132 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
9133 {
9134         double index, f;
9135         index = parms[2] + r_refdef.scene.time * parms[3];
9136         index -= floor(index);
9137         switch (func)
9138         {
9139         default:
9140         case Q3WAVEFUNC_NONE:
9141         case Q3WAVEFUNC_NOISE:
9142         case Q3WAVEFUNC_COUNT:
9143                 f = 0;
9144                 break;
9145         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
9146         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
9147         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
9148         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
9149         case Q3WAVEFUNC_TRIANGLE:
9150                 index *= 4;
9151                 f = index - floor(index);
9152                 if (index < 1)
9153                         f = f;
9154                 else if (index < 2)
9155                         f = 1 - f;
9156                 else if (index < 3)
9157                         f = -f;
9158                 else
9159                         f = -(1 - f);
9160                 break;
9161         }
9162         return (float)(parms[0] + parms[1] * f);
9163 }
9164
9165 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
9166 {
9167         int w, h, idx;
9168         float f;
9169         float tcmat[12];
9170         matrix4x4_t matrix, temp;
9171         switch(tcmod->tcmod)
9172         {
9173                 case Q3TCMOD_COUNT:
9174                 case Q3TCMOD_NONE:
9175                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9176                                 matrix = r_waterscrollmatrix;
9177                         else
9178                                 matrix = identitymatrix;
9179                         break;
9180                 case Q3TCMOD_ENTITYTRANSLATE:
9181                         // this is used in Q3 to allow the gamecode to control texcoord
9182                         // scrolling on the entity, which is not supported in darkplaces yet.
9183                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
9184                         break;
9185                 case Q3TCMOD_ROTATE:
9186                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
9187                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
9188                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
9189                         break;
9190                 case Q3TCMOD_SCALE:
9191                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
9192                         break;
9193                 case Q3TCMOD_SCROLL:
9194                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
9195                         break;
9196                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
9197                         w = (int) tcmod->parms[0];
9198                         h = (int) tcmod->parms[1];
9199                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
9200                         f = f - floor(f);
9201                         idx = (int) floor(f * w * h);
9202                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
9203                         break;
9204                 case Q3TCMOD_STRETCH:
9205                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
9206                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
9207                         break;
9208                 case Q3TCMOD_TRANSFORM:
9209                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
9210                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
9211                         VectorSet(tcmat +  6, 0                   , 0                , 1);
9212                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
9213                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
9214                         break;
9215                 case Q3TCMOD_TURBULENT:
9216                         // this is handled in the RSurf_PrepareVertices function
9217                         matrix = identitymatrix;
9218                         break;
9219         }
9220         temp = *texmatrix;
9221         Matrix4x4_Concat(texmatrix, &matrix, &temp);
9222 }
9223
9224 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
9225 {
9226         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
9227         char name[MAX_QPATH];
9228         skinframe_t *skinframe;
9229         unsigned char pixels[296*194];
9230         strlcpy(cache->name, skinname, sizeof(cache->name));
9231         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
9232         if (developer_loading.integer)
9233                 Con_Printf("loading %s\n", name);
9234         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
9235         if (!skinframe || !skinframe->base)
9236         {
9237                 unsigned char *f;
9238                 fs_offset_t filesize;
9239                 skinframe = NULL;
9240                 f = FS_LoadFile(name, tempmempool, true, &filesize);
9241                 if (f)
9242                 {
9243                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
9244                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
9245                         Mem_Free(f);
9246                 }
9247         }
9248         cache->skinframe = skinframe;
9249 }
9250
9251 texture_t *R_GetCurrentTexture(texture_t *t)
9252 {
9253         int i;
9254         const entity_render_t *ent = rsurface.entity;
9255         dp_model_t *model = ent->model;
9256         q3shaderinfo_layer_tcmod_t *tcmod;
9257
9258         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
9259                 return t->currentframe;
9260         t->update_lastrenderframe = r_textureframe;
9261         t->update_lastrenderentity = (void *)ent;
9262
9263         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
9264                 t->camera_entity = ent->entitynumber;
9265         else
9266                 t->camera_entity = 0;
9267
9268         // switch to an alternate material if this is a q1bsp animated material
9269         {
9270                 texture_t *texture = t;
9271                 int s = rsurface.ent_skinnum;
9272                 if ((unsigned int)s >= (unsigned int)model->numskins)
9273                         s = 0;
9274                 if (model->skinscenes)
9275                 {
9276                         if (model->skinscenes[s].framecount > 1)
9277                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
9278                         else
9279                                 s = model->skinscenes[s].firstframe;
9280                 }
9281                 if (s > 0)
9282                         t = t + s * model->num_surfaces;
9283                 if (t->animated)
9284                 {
9285                         // use an alternate animation if the entity's frame is not 0,
9286                         // and only if the texture has an alternate animation
9287                         if (rsurface.ent_alttextures && t->anim_total[1])
9288                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
9289                         else
9290                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
9291                 }
9292                 texture->currentframe = t;
9293         }
9294
9295         // update currentskinframe to be a qw skin or animation frame
9296         if (rsurface.ent_qwskin >= 0)
9297         {
9298                 i = rsurface.ent_qwskin;
9299                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
9300                 {
9301                         r_qwskincache_size = cl.maxclients;
9302                         if (r_qwskincache)
9303                                 Mem_Free(r_qwskincache);
9304                         r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
9305                 }
9306                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
9307                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
9308                 t->currentskinframe = r_qwskincache[i].skinframe;
9309                 if (t->currentskinframe == NULL)
9310                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9311         }
9312         else if (t->numskinframes >= 2)
9313                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9314         if (t->backgroundnumskinframes >= 2)
9315                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
9316
9317         t->currentmaterialflags = t->basematerialflags;
9318         t->currentalpha = rsurface.colormod[3];
9319         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
9320                 t->currentalpha *= r_wateralpha.value;
9321         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
9322                 t->currentalpha *= t->r_water_wateralpha;
9323         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
9324                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
9325         if (!(rsurface.ent_flags & RENDER_LIGHT))
9326                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
9327         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
9328         {
9329                 // pick a model lighting mode
9330                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
9331                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
9332                 else
9333                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
9334         }
9335         if (rsurface.ent_flags & RENDER_ADDITIVE)
9336                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9337         else if (t->currentalpha < 1)
9338                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9339         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
9340                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
9341         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
9342                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
9343         if (t->backgroundnumskinframes)
9344                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
9345         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
9346         {
9347                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
9348                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
9349         }
9350         else
9351                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
9352         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
9353                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
9354
9355         // there is no tcmod
9356         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9357         {
9358                 t->currenttexmatrix = r_waterscrollmatrix;
9359                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
9360         }
9361         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
9362         {
9363                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
9364                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
9365         }
9366
9367         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9368                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
9369         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9370                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
9371
9372         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
9373         if (t->currentskinframe->qpixels)
9374                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
9375         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
9376         if (!t->basetexture)
9377                 t->basetexture = r_texture_notexture;
9378         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
9379         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
9380         t->nmaptexture = t->currentskinframe->nmap;
9381         if (!t->nmaptexture)
9382                 t->nmaptexture = r_texture_blanknormalmap;
9383         t->glosstexture = r_texture_black;
9384         t->glowtexture = t->currentskinframe->glow;
9385         t->fogtexture = t->currentskinframe->fog;
9386         t->reflectmasktexture = t->currentskinframe->reflect;
9387         if (t->backgroundnumskinframes)
9388         {
9389                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
9390                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
9391                 t->backgroundglosstexture = r_texture_black;
9392                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
9393                 if (!t->backgroundnmaptexture)
9394                         t->backgroundnmaptexture = r_texture_blanknormalmap;
9395         }
9396         else
9397         {
9398                 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
9399                 t->backgroundnmaptexture = r_texture_blanknormalmap;
9400                 t->backgroundglosstexture = r_texture_black;
9401                 t->backgroundglowtexture = NULL;
9402         }
9403         t->specularpower = r_shadow_glossexponent.value;
9404         // TODO: store reference values for these in the texture?
9405         t->specularscale = 0;
9406         if (r_shadow_gloss.integer > 0)
9407         {
9408                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
9409                 {
9410                         if (r_shadow_glossintensity.value > 0)
9411                         {
9412                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
9413                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
9414                                 t->specularscale = r_shadow_glossintensity.value;
9415                         }
9416                 }
9417                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
9418                 {
9419                         t->glosstexture = r_texture_white;
9420                         t->backgroundglosstexture = r_texture_white;
9421                         t->specularscale = r_shadow_gloss2intensity.value;
9422                         t->specularpower = r_shadow_gloss2exponent.value;
9423                 }
9424         }
9425         t->specularscale *= t->specularscalemod;
9426         t->specularpower *= t->specularpowermod;
9427
9428         // lightmaps mode looks bad with dlights using actual texturing, so turn
9429         // off the colormap and glossmap, but leave the normalmap on as it still
9430         // accurately represents the shading involved
9431         if (gl_lightmaps.integer)
9432         {
9433                 t->basetexture = r_texture_grey128;
9434                 t->pantstexture = r_texture_black;
9435                 t->shirttexture = r_texture_black;
9436                 t->nmaptexture = r_texture_blanknormalmap;
9437                 t->glosstexture = r_texture_black;
9438                 t->glowtexture = NULL;
9439                 t->fogtexture = NULL;
9440                 t->reflectmasktexture = NULL;
9441                 t->backgroundbasetexture = NULL;
9442                 t->backgroundnmaptexture = r_texture_blanknormalmap;
9443                 t->backgroundglosstexture = r_texture_black;
9444                 t->backgroundglowtexture = NULL;
9445                 t->specularscale = 0;
9446                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
9447         }
9448
9449         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
9450         VectorClear(t->dlightcolor);
9451         t->currentnumlayers = 0;
9452         if (t->currentmaterialflags & MATERIALFLAG_WALL)
9453         {
9454                 int blendfunc1, blendfunc2;
9455                 qboolean depthmask;
9456                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
9457                 {
9458                         blendfunc1 = GL_SRC_ALPHA;
9459                         blendfunc2 = GL_ONE;
9460                 }
9461                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
9462                 {
9463                         blendfunc1 = GL_SRC_ALPHA;
9464                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
9465                 }
9466                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9467                 {
9468                         blendfunc1 = t->customblendfunc[0];
9469                         blendfunc2 = t->customblendfunc[1];
9470                 }
9471                 else
9472                 {
9473                         blendfunc1 = GL_ONE;
9474                         blendfunc2 = GL_ZERO;
9475                 }
9476                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
9477                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9478                 {
9479                         // fullbright is not affected by r_refdef.lightmapintensity
9480                         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]);
9481                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9482                                 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]);
9483                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9484                                 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]);
9485                 }
9486                 else
9487                 {
9488                         vec3_t ambientcolor;
9489                         float colorscale;
9490                         // set the color tint used for lights affecting this surface
9491                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
9492                         colorscale = 2;
9493                         // q3bsp has no lightmap updates, so the lightstylevalue that
9494                         // would normally be baked into the lightmap must be
9495                         // applied to the color
9496                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
9497                         if (model->type == mod_brushq3)
9498                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
9499                         colorscale *= r_refdef.lightmapintensity;
9500                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
9501                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
9502                         // basic lit geometry
9503                         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]);
9504                         // add pants/shirt if needed
9505                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9506                                 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]);
9507                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9508                                 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]);
9509                         // now add ambient passes if needed
9510                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
9511                         {
9512                                 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]);
9513                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9514                                         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]);
9515                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9516                                         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]);
9517                         }
9518                 }
9519                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
9520                         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]);
9521                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
9522                 {
9523                         // if this is opaque use alpha blend which will darken the earlier
9524                         // passes cheaply.
9525                         //
9526                         // if this is an alpha blended material, all the earlier passes
9527                         // were darkened by fog already, so we only need to add the fog
9528                         // color ontop through the fog mask texture
9529                         //
9530                         // if this is an additive blended material, all the earlier passes
9531                         // were darkened by fog already, and we should not add fog color
9532                         // (because the background was not darkened, there is no fog color
9533                         // that was lost behind it).
9534                         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]);
9535                 }
9536         }
9537
9538         return t->currentframe;
9539 }
9540
9541 rsurfacestate_t rsurface;
9542
9543 void R_Mesh_ResizeArrays(int newvertices)
9544 {
9545         float *base;
9546         if (rsurface.array_size >= newvertices)
9547                 return;
9548         if (rsurface.array_modelvertex3f)
9549                 Mem_Free(rsurface.array_modelvertex3f);
9550         rsurface.array_size = (newvertices + 1023) & ~1023;
9551         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
9552         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
9553         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
9554         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
9555         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
9556         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
9557         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
9558         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
9559         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
9560         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
9561         rsurface.array_color4f           = base + rsurface.array_size * 27;
9562         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
9563 }
9564
9565 void RSurf_ActiveWorldEntity(void)
9566 {
9567         dp_model_t *model = r_refdef.scene.worldmodel;
9568         //if (rsurface.entity == r_refdef.scene.worldentity)
9569         //      return;
9570         rsurface.entity = r_refdef.scene.worldentity;
9571         rsurface.skeleton = NULL;
9572         rsurface.ent_skinnum = 0;
9573         rsurface.ent_qwskin = -1;
9574         rsurface.ent_shadertime = 0;
9575         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
9576         if (rsurface.array_size < model->surfmesh.num_vertices)
9577                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9578         rsurface.matrix = identitymatrix;
9579         rsurface.inversematrix = identitymatrix;
9580         rsurface.matrixscale = 1;
9581         rsurface.inversematrixscale = 1;
9582         R_EntityMatrix(&identitymatrix);
9583         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
9584         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
9585         rsurface.fograngerecip = r_refdef.fograngerecip;
9586         rsurface.fogheightfade = r_refdef.fogheightfade;
9587         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
9588         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9589         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9590         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9591         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9592         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9593         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9594         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
9595         rsurface.colormod[3] = 1;
9596         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);
9597         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9598         rsurface.frameblend[0].lerp = 1;
9599         rsurface.ent_alttextures = false;
9600         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9601         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9602         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
9603         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9604         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9605         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9606         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9607         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9608         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9609         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9610         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9611         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
9612         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9613         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9614         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
9615         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9616         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9617         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
9618         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9619         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9620         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
9621         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9622         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9623         rsurface.modelelement3i = model->surfmesh.data_element3i;
9624         rsurface.modelelement3s = model->surfmesh.data_element3s;
9625         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9626         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9627         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9628         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9629         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9630         rsurface.modelsurfaces = model->data_surfaces;
9631         rsurface.generatedvertex = false;
9632         rsurface.vertex3f  = rsurface.modelvertex3f;
9633         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9634         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9635         rsurface.svector3f = rsurface.modelsvector3f;
9636         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9637         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9638         rsurface.tvector3f = rsurface.modeltvector3f;
9639         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9640         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9641         rsurface.normal3f  = rsurface.modelnormal3f;
9642         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9643         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9644         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9645 }
9646
9647 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
9648 {
9649         dp_model_t *model = ent->model;
9650         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
9651         //      return;
9652         rsurface.entity = (entity_render_t *)ent;
9653         rsurface.skeleton = ent->skeleton;
9654         rsurface.ent_skinnum = ent->skinnum;
9655         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;
9656         rsurface.ent_shadertime = ent->shadertime;
9657         rsurface.ent_flags = ent->flags;
9658         if (rsurface.array_size < model->surfmesh.num_vertices)
9659                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9660         rsurface.matrix = ent->matrix;
9661         rsurface.inversematrix = ent->inversematrix;
9662         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9663         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9664         R_EntityMatrix(&rsurface.matrix);
9665         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9666         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9667         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9668         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9669         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9670         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9671         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
9672         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
9673         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
9674         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
9675         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
9676         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
9677         rsurface.colormod[3] = ent->alpha;
9678         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
9679         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
9680         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
9681         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9682         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9683         if (ent->model->brush.submodel && !prepass)
9684         {
9685                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
9686                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
9687         }
9688         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
9689         {
9690                 if (ent->animcache_vertex3f && !r_framedata_failed)
9691                 {
9692                         rsurface.modelvertex3f = ent->animcache_vertex3f;
9693                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
9694                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
9695                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
9696                 }
9697                 else if (wanttangents)
9698                 {
9699                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9700                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9701                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9702                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9703                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
9704                 }
9705                 else if (wantnormals)
9706                 {
9707                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9708                         rsurface.modelsvector3f = NULL;
9709                         rsurface.modeltvector3f = NULL;
9710                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9711                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
9712                 }
9713                 else
9714                 {
9715                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9716                         rsurface.modelsvector3f = NULL;
9717                         rsurface.modeltvector3f = NULL;
9718                         rsurface.modelnormal3f = NULL;
9719                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
9720                 }
9721                 rsurface.modelvertex3f_bufferobject = 0;
9722                 rsurface.modelvertex3f_bufferoffset = 0;
9723                 rsurface.modelsvector3f_bufferobject = 0;
9724                 rsurface.modelsvector3f_bufferoffset = 0;
9725                 rsurface.modeltvector3f_bufferobject = 0;
9726                 rsurface.modeltvector3f_bufferoffset = 0;
9727                 rsurface.modelnormal3f_bufferobject = 0;
9728                 rsurface.modelnormal3f_bufferoffset = 0;
9729                 rsurface.generatedvertex = true;
9730         }
9731         else
9732         {
9733                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
9734                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9735                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9736                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9737                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9738                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9739                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9740                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9741                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9742                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
9743                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9744                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9745                 rsurface.generatedvertex = false;
9746         }
9747         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
9748         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9749         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9750         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
9751         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9752         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9753         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
9754         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9755         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9756         rsurface.modelelement3i = model->surfmesh.data_element3i;
9757         rsurface.modelelement3s = model->surfmesh.data_element3s;
9758         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9759         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9760         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9761         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9762         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9763         rsurface.modelsurfaces = model->data_surfaces;
9764         rsurface.vertex3f  = rsurface.modelvertex3f;
9765         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9766         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9767         rsurface.svector3f = rsurface.modelsvector3f;
9768         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9769         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9770         rsurface.tvector3f = rsurface.modeltvector3f;
9771         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9772         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9773         rsurface.normal3f  = rsurface.modelnormal3f;
9774         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9775         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9776         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9777 }
9778
9779 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)
9780 {
9781         rsurface.entity = r_refdef.scene.worldentity;
9782         rsurface.skeleton = NULL;
9783         rsurface.ent_skinnum = 0;
9784         rsurface.ent_qwskin = -1;
9785         rsurface.ent_shadertime = shadertime;
9786         rsurface.ent_flags = entflags;
9787         rsurface.modelnum_vertices = numvertices;
9788         rsurface.modelnum_triangles = numtriangles;
9789         if (rsurface.array_size < rsurface.modelnum_vertices)
9790                 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
9791         rsurface.matrix = *matrix;
9792         rsurface.inversematrix = *inversematrix;
9793         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9794         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9795         R_EntityMatrix(&rsurface.matrix);
9796         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9797         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9798         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9799         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9800         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9801         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9802         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9803         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9804         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9805         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9806         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9807         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
9808         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);
9809         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9810         rsurface.frameblend[0].lerp = 1;
9811         rsurface.ent_alttextures = false;
9812         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9813         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9814         if (wanttangents)
9815         {
9816                 rsurface.modelvertex3f = vertex3f;
9817                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
9818                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
9819                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9820         }
9821         else if (wantnormals)
9822         {
9823                 rsurface.modelvertex3f = vertex3f;
9824                 rsurface.modelsvector3f = NULL;
9825                 rsurface.modeltvector3f = NULL;
9826                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9827         }
9828         else
9829         {
9830                 rsurface.modelvertex3f = vertex3f;
9831                 rsurface.modelsvector3f = NULL;
9832                 rsurface.modeltvector3f = NULL;
9833                 rsurface.modelnormal3f = NULL;
9834         }
9835         rsurface.modelvertex3f_bufferobject = 0;
9836         rsurface.modelvertex3f_bufferoffset = 0;
9837         rsurface.modelsvector3f_bufferobject = 0;
9838         rsurface.modelsvector3f_bufferoffset = 0;
9839         rsurface.modeltvector3f_bufferobject = 0;
9840         rsurface.modeltvector3f_bufferoffset = 0;
9841         rsurface.modelnormal3f_bufferobject = 0;
9842         rsurface.modelnormal3f_bufferoffset = 0;
9843         rsurface.generatedvertex = true;
9844         rsurface.modellightmapcolor4f  = color4f;
9845         rsurface.modellightmapcolor4f_bufferobject = 0;
9846         rsurface.modellightmapcolor4f_bufferoffset = 0;
9847         rsurface.modeltexcoordtexture2f  = texcoord2f;
9848         rsurface.modeltexcoordtexture2f_bufferobject = 0;
9849         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9850         rsurface.modeltexcoordlightmap2f  = NULL;
9851         rsurface.modeltexcoordlightmap2f_bufferobject = 0;
9852         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9853         rsurface.modelelement3i = element3i;
9854         rsurface.modelelement3s = element3s;
9855         rsurface.modelelement3i_bufferobject = 0;
9856         rsurface.modelelement3s_bufferobject = 0;
9857         rsurface.modellightmapoffsets = NULL;
9858         rsurface.modelsurfaces = NULL;
9859         rsurface.vertex3f  = rsurface.modelvertex3f;
9860         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9861         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9862         rsurface.svector3f = rsurface.modelsvector3f;
9863         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9864         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9865         rsurface.tvector3f = rsurface.modeltvector3f;
9866         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9867         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9868         rsurface.normal3f  = rsurface.modelnormal3f;
9869         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9870         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9871         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9872
9873         if (rsurface.modelnum_vertices && rsurface.modelelement3i)
9874         {
9875                 if ((wantnormals || wanttangents) && !normal3f)
9876                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9877                 if (wanttangents && !svector3f)
9878                         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);
9879         }
9880 }
9881
9882 float RSurf_FogPoint(const float *v)
9883 {
9884         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9885         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9886         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9887         float FogHeightFade = r_refdef.fogheightfade;
9888         float fogfrac;
9889         unsigned int fogmasktableindex;
9890         if (r_refdef.fogplaneviewabove)
9891                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9892         else
9893                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9894         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9895         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9896 }
9897
9898 float RSurf_FogVertex(const float *v)
9899 {
9900         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9901         float FogPlaneViewDist = rsurface.fogplaneviewdist;
9902         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9903         float FogHeightFade = rsurface.fogheightfade;
9904         float fogfrac;
9905         unsigned int fogmasktableindex;
9906         if (r_refdef.fogplaneviewabove)
9907                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9908         else
9909                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9910         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9911         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9912 }
9913
9914 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9915 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9916 {
9917         int deformindex;
9918         int texturesurfaceindex;
9919         int i, j;
9920         float amplitude;
9921         float animpos;
9922         float scale;
9923         const float *v1, *in_tc;
9924         float *out_tc;
9925         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9926         float waveparms[4];
9927         q3shaderinfo_deform_t *deform;
9928         // 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
9929         if (rsurface.generatedvertex)
9930         {
9931                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
9932                         generatenormals = true;
9933                 for (i = 0;i < Q3MAXDEFORMS;i++)
9934                 {
9935                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
9936                         {
9937                                 generatetangents = true;
9938                                 generatenormals = true;
9939                         }
9940                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
9941                                 generatenormals = true;
9942                 }
9943                 if (generatenormals && !rsurface.modelnormal3f)
9944                 {
9945                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9946                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
9947                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
9948                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9949                 }
9950                 if (generatetangents && !rsurface.modelsvector3f)
9951                 {
9952                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9953                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
9954                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
9955                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9956                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
9957                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
9958                         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);
9959                 }
9960         }
9961         rsurface.vertex3f  = rsurface.modelvertex3f;
9962         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9963         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9964         rsurface.svector3f = rsurface.modelsvector3f;
9965         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9966         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9967         rsurface.tvector3f = rsurface.modeltvector3f;
9968         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9969         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9970         rsurface.normal3f  = rsurface.modelnormal3f;
9971         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9972         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9973         // if vertices are deformed (sprite flares and things in maps, possibly
9974         // water waves, bulges and other deformations), generate them into
9975         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
9976         // (may be static model data or generated data for an animated model, or
9977         //  the previous deform pass)
9978         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
9979         {
9980                 switch (deform->deform)
9981                 {
9982                 default:
9983                 case Q3DEFORM_PROJECTIONSHADOW:
9984                 case Q3DEFORM_TEXT0:
9985                 case Q3DEFORM_TEXT1:
9986                 case Q3DEFORM_TEXT2:
9987                 case Q3DEFORM_TEXT3:
9988                 case Q3DEFORM_TEXT4:
9989                 case Q3DEFORM_TEXT5:
9990                 case Q3DEFORM_TEXT6:
9991                 case Q3DEFORM_TEXT7:
9992                 case Q3DEFORM_NONE:
9993                         break;
9994                 case Q3DEFORM_AUTOSPRITE:
9995                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9996                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9997                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9998                         VectorNormalize(newforward);
9999                         VectorNormalize(newright);
10000                         VectorNormalize(newup);
10001                         // make deformed versions of only the model vertices used by the specified surfaces
10002                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10003                         {
10004                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10005                                 // a single autosprite surface can contain multiple sprites...
10006                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
10007                                 {
10008                                         VectorClear(center);
10009                                         for (i = 0;i < 4;i++)
10010                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
10011                                         VectorScale(center, 0.25f, center);
10012                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
10013                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
10014                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
10015                                         for (i = 0;i < 4;i++)
10016                                         {
10017                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
10018                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
10019                                         }
10020                                 }
10021                                 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);
10022                                 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);
10023                         }
10024                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
10025                         rsurface.vertex3f_bufferobject = 0;
10026                         rsurface.vertex3f_bufferoffset = 0;
10027                         rsurface.svector3f = rsurface.array_deformedsvector3f;
10028                         rsurface.svector3f_bufferobject = 0;
10029                         rsurface.svector3f_bufferoffset = 0;
10030                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
10031                         rsurface.tvector3f_bufferobject = 0;
10032                         rsurface.tvector3f_bufferoffset = 0;
10033                         rsurface.normal3f = rsurface.array_deformednormal3f;
10034                         rsurface.normal3f_bufferobject = 0;
10035                         rsurface.normal3f_bufferoffset = 0;
10036                         break;
10037                 case Q3DEFORM_AUTOSPRITE2:
10038                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
10039                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
10040                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
10041                         VectorNormalize(newforward);
10042                         VectorNormalize(newright);
10043                         VectorNormalize(newup);
10044                         // make deformed versions of only the model vertices used by the specified surfaces
10045                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10046                         {
10047                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10048                                 const float *v1, *v2;
10049                                 vec3_t start, end;
10050                                 float f, l;
10051                                 struct
10052                                 {
10053                                         float length2;
10054                                         const float *v1;
10055                                         const float *v2;
10056                                 }
10057                                 shortest[2];
10058                                 memset(shortest, 0, sizeof(shortest));
10059                                 // a single autosprite surface can contain multiple sprites...
10060                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
10061                                 {
10062                                         VectorClear(center);
10063                                         for (i = 0;i < 4;i++)
10064                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
10065                                         VectorScale(center, 0.25f, center);
10066                                         // find the two shortest edges, then use them to define the
10067                                         // axis vectors for rotating around the central axis
10068                                         for (i = 0;i < 6;i++)
10069                                         {
10070                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
10071                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
10072 #if 0
10073                                                 Debug_PolygonBegin(NULL, 0);
10074                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
10075                                                 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);
10076                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
10077                                                 Debug_PolygonEnd();
10078 #endif
10079                                                 l = VectorDistance2(v1, v2);
10080                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
10081                                                 if (v1[2] != v2[2])
10082                                                         l += (1.0f / 1024.0f);
10083                                                 if (shortest[0].length2 > l || i == 0)
10084                                                 {
10085                                                         shortest[1] = shortest[0];
10086                                                         shortest[0].length2 = l;
10087                                                         shortest[0].v1 = v1;
10088                                                         shortest[0].v2 = v2;
10089                                                 }
10090                                                 else if (shortest[1].length2 > l || i == 1)
10091                                                 {
10092                                                         shortest[1].length2 = l;
10093                                                         shortest[1].v1 = v1;
10094                                                         shortest[1].v2 = v2;
10095                                                 }
10096                                         }
10097                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
10098                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
10099 #if 0
10100                                         Debug_PolygonBegin(NULL, 0);
10101                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
10102                                         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);
10103                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
10104                                         Debug_PolygonEnd();
10105 #endif
10106                                         // this calculates the right vector from the shortest edge
10107                                         // and the up vector from the edge midpoints
10108                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
10109                                         VectorNormalize(right);
10110                                         VectorSubtract(end, start, up);
10111                                         VectorNormalize(up);
10112                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
10113                                         VectorSubtract(rsurface.localvieworigin, center, forward);
10114                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
10115                                         VectorNegate(forward, forward);
10116                                         VectorReflect(forward, 0, up, forward);
10117                                         VectorNormalize(forward);
10118                                         CrossProduct(up, forward, newright);
10119                                         VectorNormalize(newright);
10120 #if 0
10121                                         Debug_PolygonBegin(NULL, 0);
10122                                         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);
10123                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
10124                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
10125                                         Debug_PolygonEnd();
10126 #endif
10127 #if 0
10128                                         Debug_PolygonBegin(NULL, 0);
10129                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
10130                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
10131                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
10132                                         Debug_PolygonEnd();
10133 #endif
10134                                         // rotate the quad around the up axis vector, this is made
10135                                         // especially easy by the fact we know the quad is flat,
10136                                         // so we only have to subtract the center position and
10137                                         // measure distance along the right vector, and then
10138                                         // multiply that by the newright vector and add back the
10139                                         // center position
10140                                         // we also need to subtract the old position to undo the
10141                                         // displacement from the center, which we do with a
10142                                         // DotProduct, the subtraction/addition of center is also
10143                                         // optimized into DotProducts here
10144                                         l = DotProduct(right, center);
10145                                         for (i = 0;i < 4;i++)
10146                                         {
10147                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
10148                                                 f = DotProduct(right, v1) - l;
10149                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
10150                                         }
10151                                 }
10152                                 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);
10153                                 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);
10154                         }
10155                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
10156                         rsurface.vertex3f_bufferobject = 0;
10157                         rsurface.vertex3f_bufferoffset = 0;
10158                         rsurface.svector3f = rsurface.array_deformedsvector3f;
10159                         rsurface.svector3f_bufferobject = 0;
10160                         rsurface.svector3f_bufferoffset = 0;
10161                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
10162                         rsurface.tvector3f_bufferobject = 0;
10163                         rsurface.tvector3f_bufferoffset = 0;
10164                         rsurface.normal3f = rsurface.array_deformednormal3f;
10165                         rsurface.normal3f_bufferobject = 0;
10166                         rsurface.normal3f_bufferoffset = 0;
10167                         break;
10168                 case Q3DEFORM_NORMAL:
10169                         // deform the normals to make reflections wavey
10170                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10171                         {
10172                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10173                                 for (j = 0;j < surface->num_vertices;j++)
10174                                 {
10175                                         float vertex[3];
10176                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
10177                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
10178                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
10179                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
10180                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
10181                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
10182                                         VectorNormalize(normal);
10183                                 }
10184                                 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);
10185                         }
10186                         rsurface.svector3f = rsurface.array_deformedsvector3f;
10187                         rsurface.svector3f_bufferobject = 0;
10188                         rsurface.svector3f_bufferoffset = 0;
10189                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
10190                         rsurface.tvector3f_bufferobject = 0;
10191                         rsurface.tvector3f_bufferoffset = 0;
10192                         rsurface.normal3f = rsurface.array_deformednormal3f;
10193                         rsurface.normal3f_bufferobject = 0;
10194                         rsurface.normal3f_bufferoffset = 0;
10195                         break;
10196                 case Q3DEFORM_WAVE:
10197                         // deform vertex array to make wavey water and flags and such
10198                         waveparms[0] = deform->waveparms[0];
10199                         waveparms[1] = deform->waveparms[1];
10200                         waveparms[2] = deform->waveparms[2];
10201                         waveparms[3] = deform->waveparms[3];
10202                         // this is how a divisor of vertex influence on deformation
10203                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10204                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10205                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10206                         {
10207                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10208                                 for (j = 0;j < surface->num_vertices;j++)
10209                                 {
10210                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
10211                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
10212                                         // if the wavefunc depends on time, evaluate it per-vertex
10213                                         if (waveparms[3])
10214                                         {
10215                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
10216                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10217                                         }
10218                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
10219                                 }
10220                         }
10221                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
10222                         rsurface.vertex3f_bufferobject = 0;
10223                         rsurface.vertex3f_bufferoffset = 0;
10224                         break;
10225                 case Q3DEFORM_BULGE:
10226                         // deform vertex array to make the surface have moving bulges
10227                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10228                         {
10229                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10230                                 for (j = 0;j < surface->num_vertices;j++)
10231                                 {
10232                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
10233                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
10234                                 }
10235                         }
10236                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
10237                         rsurface.vertex3f_bufferobject = 0;
10238                         rsurface.vertex3f_bufferoffset = 0;
10239                         break;
10240                 case Q3DEFORM_MOVE:
10241                         // deform vertex array
10242                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10243                         VectorScale(deform->parms, scale, waveparms);
10244                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10245                         {
10246                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10247                                 for (j = 0;j < surface->num_vertices;j++)
10248                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
10249                         }
10250                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
10251                         rsurface.vertex3f_bufferobject = 0;
10252                         rsurface.vertex3f_bufferoffset = 0;
10253                         break;
10254                 }
10255         }
10256         // generate texcoords based on the chosen texcoord source
10257         switch(rsurface.texture->tcgen.tcgen)
10258         {
10259         default:
10260         case Q3TCGEN_TEXTURE:
10261                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
10262                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
10263                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
10264                 break;
10265         case Q3TCGEN_LIGHTMAP:
10266                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
10267                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
10268                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
10269                 break;
10270         case Q3TCGEN_VECTOR:
10271                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10272                 {
10273                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10274                         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)
10275                         {
10276                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
10277                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
10278                         }
10279                 }
10280                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
10281                 rsurface.texcoordtexture2f_bufferobject  = 0;
10282                 rsurface.texcoordtexture2f_bufferoffset  = 0;
10283                 break;
10284         case Q3TCGEN_ENVIRONMENT:
10285                 // make environment reflections using a spheremap
10286                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10287                 {
10288                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10289                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
10290                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
10291                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
10292                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
10293                         {
10294                                 // identical to Q3A's method, but executed in worldspace so
10295                                 // carried models can be shiny too
10296
10297                                 float viewer[3], d, reflected[3], worldreflected[3];
10298
10299                                 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
10300                                 // VectorNormalize(viewer);
10301
10302                                 d = DotProduct(normal, viewer);
10303
10304                                 reflected[0] = normal[0]*2*d - viewer[0];
10305                                 reflected[1] = normal[1]*2*d - viewer[1];
10306                                 reflected[2] = normal[2]*2*d - viewer[2];
10307                                 // note: this is proportinal to viewer, so we can normalize later
10308
10309                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10310                                 VectorNormalize(worldreflected);
10311
10312                                 // note: this sphere map only uses world x and z!
10313                                 // so positive and negative y will LOOK THE SAME.
10314                                 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
10315                                 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
10316                         }
10317                 }
10318                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
10319                 rsurface.texcoordtexture2f_bufferobject  = 0;
10320                 rsurface.texcoordtexture2f_bufferoffset  = 0;
10321                 break;
10322         }
10323         // the only tcmod that needs software vertex processing is turbulent, so
10324         // check for it here and apply the changes if needed
10325         // and we only support that as the first one
10326         // (handling a mixture of turbulent and other tcmods would be problematic
10327         //  without punting it entirely to a software path)
10328         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10329         {
10330                 amplitude = rsurface.texture->tcmods[0].parms[1];
10331                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
10332                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10333                 {
10334                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10335                         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)
10336                         {
10337                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10338                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10339                         }
10340                 }
10341                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
10342                 rsurface.texcoordtexture2f_bufferobject  = 0;
10343                 rsurface.texcoordtexture2f_bufferoffset  = 0;
10344         }
10345         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
10346         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
10347         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
10348         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
10349 }
10350
10351 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10352 {
10353         int i, j;
10354         const msurface_t *surface = texturesurfacelist[0];
10355         const msurface_t *surface2;
10356         int firstvertex;
10357         int endvertex;
10358         int numvertices;
10359         int numtriangles;
10360         // TODO: lock all array ranges before render, rather than on each surface
10361         if (texturenumsurfaces == 1)
10362                 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);
10363         else if (r_batchmode.integer == 2)
10364         {
10365                 #define MAXBATCHTRIANGLES 65536
10366                 int batchtriangles = 0;
10367                 static int batchelements[MAXBATCHTRIANGLES*3];
10368                 for (i = 0;i < texturenumsurfaces;i = j)
10369                 {
10370                         surface = texturesurfacelist[i];
10371                         j = i + 1;
10372                         if (surface->num_triangles > MAXBATCHTRIANGLES)
10373                         {
10374                                 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);
10375                                 continue;
10376                         }
10377                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
10378                         batchtriangles = surface->num_triangles;
10379                         firstvertex = surface->num_firstvertex;
10380                         endvertex = surface->num_firstvertex + surface->num_vertices;
10381                         for (;j < texturenumsurfaces;j++)
10382                         {
10383                                 surface2 = texturesurfacelist[j];
10384                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
10385                                         break;
10386                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
10387                                 batchtriangles += surface2->num_triangles;
10388                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
10389                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
10390                         }
10391                         surface2 = texturesurfacelist[j-1];
10392                         numvertices = endvertex - firstvertex;
10393                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
10394                 }
10395         }
10396         else if (r_batchmode.integer == 1)
10397         {
10398                 for (i = 0;i < texturenumsurfaces;i = j)
10399                 {
10400                         surface = texturesurfacelist[i];
10401                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10402                                 if (texturesurfacelist[j] != surface2)
10403                                         break;
10404                         surface2 = texturesurfacelist[j-1];
10405                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
10406                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
10407                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10408                 }
10409         }
10410         else
10411         {
10412                 for (i = 0;i < texturenumsurfaces;i++)
10413                 {
10414                         surface = texturesurfacelist[i];
10415                         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);
10416                 }
10417         }
10418 }
10419
10420 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
10421 {
10422         switch(vid.renderpath)
10423         {
10424         case RENDERPATH_CGGL:
10425 #ifdef SUPPORTCG
10426                 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
10427                 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
10428 #endif
10429                 break;
10430         case RENDERPATH_GL20:
10431                 if (r_glsl_permutation->loc_Texture_Lightmap  >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
10432                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
10433                 break;
10434         case RENDERPATH_GL13:
10435         case RENDERPATH_GL11:
10436                 R_Mesh_TexBind(0, surface->lightmaptexture);
10437                 break;
10438         }
10439 }
10440
10441 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
10442 {
10443         // pick the closest matching water plane and bind textures
10444         int planeindex, vertexindex;
10445         float d, bestd;
10446         vec3_t vert;
10447         const float *v;
10448         r_waterstate_waterplane_t *p, *bestp;
10449         bestd = 0;
10450         bestp = NULL;
10451         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
10452         {
10453                 if(p->camera_entity != rsurface.texture->camera_entity)
10454                         continue;
10455                 d = 0;
10456                 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
10457                 {
10458                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10459                         d += fabs(PlaneDiff(vert, &p->plane));
10460                 }
10461                 if (bestd > d || !bestp)
10462                 {
10463                         bestd = d;
10464                         bestp = p;
10465                 }
10466         }
10467         switch(vid.renderpath)
10468         {
10469         case RENDERPATH_CGGL:
10470 #ifdef SUPPORTCG
10471                 if (r_cg_permutation->fp_Texture_Refraction) {CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR}
10472                 else if (r_cg_permutation->fp_Texture_First) {CG_BindTexture(r_cg_permutation->fp_Texture_First, bestp ? bestp->texture_camera : r_texture_black);CHECKCGERROR}
10473                 if (r_cg_permutation->fp_Texture_Reflection) {CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR}
10474 #endif
10475                 break;
10476         case RENDERPATH_GL20:
10477                 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
10478                 else if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST, bestp ? bestp->texture_camera : r_texture_black);
10479                 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
10480                 break;
10481         case RENDERPATH_GL13:
10482         case RENDERPATH_GL11:
10483                 break;
10484         }
10485 }
10486
10487 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10488 {
10489         int i;
10490         const msurface_t *surface;
10491         if (r_waterstate.renderingscene)
10492                 return;
10493         for (i = 0;i < texturenumsurfaces;i++)
10494         {
10495                 surface = texturesurfacelist[i];
10496                 RSurf_BindLightmapForSurface(surface);
10497                 RSurf_BindReflectionForSurface(surface);
10498                 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);
10499         }
10500 }
10501
10502 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10503 {
10504         int i;
10505         int j;
10506         const msurface_t *surface = texturesurfacelist[0];
10507         const msurface_t *surface2;
10508         int firstvertex;
10509         int endvertex;
10510         int numvertices;
10511         int numtriangles;
10512         if (texturenumsurfaces == 1)
10513         {
10514                 RSurf_BindLightmapForSurface(surface);
10515                 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);
10516         }
10517         else if (r_batchmode.integer == 2)
10518         {
10519                 int batchtriangles = 0;
10520                 static int batchelements[MAXBATCHTRIANGLES*3];
10521                 for (i = 0;i < texturenumsurfaces;i = j)
10522                 {
10523                         surface = texturesurfacelist[i];
10524                         RSurf_BindLightmapForSurface(surface);
10525                         j = i + 1;
10526                         if (surface->num_triangles > MAXBATCHTRIANGLES)
10527                         {
10528                                 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);
10529                                 continue;
10530                         }
10531                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
10532                         batchtriangles = surface->num_triangles;
10533                         firstvertex = surface->num_firstvertex;
10534                         endvertex = surface->num_firstvertex + surface->num_vertices;
10535                         for (;j < texturenumsurfaces;j++)
10536                         {
10537                                 surface2 = texturesurfacelist[j];
10538                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
10539                                         break;
10540                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
10541                                 batchtriangles += surface2->num_triangles;
10542                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
10543                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
10544                         }
10545                         surface2 = texturesurfacelist[j-1];
10546                         numvertices = endvertex - firstvertex;
10547                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
10548                 }
10549         }
10550         else if (r_batchmode.integer == 1)
10551         {
10552 #if 0
10553                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
10554                 for (i = 0;i < texturenumsurfaces;i = j)
10555                 {
10556                         surface = texturesurfacelist[i];
10557                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10558                                 if (texturesurfacelist[j] != surface2)
10559                                         break;
10560                         Con_Printf(" %i", j - i);
10561                 }
10562                 Con_Printf("\n");
10563                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
10564 #endif
10565                 for (i = 0;i < texturenumsurfaces;i = j)
10566                 {
10567                         surface = texturesurfacelist[i];
10568                         RSurf_BindLightmapForSurface(surface);
10569                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10570                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
10571                                         break;
10572 #if 0
10573                         Con_Printf(" %i", j - i);
10574 #endif
10575                         surface2 = texturesurfacelist[j-1];
10576                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
10577                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
10578                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10579                 }
10580 #if 0
10581                 Con_Printf("\n");
10582 #endif
10583         }
10584         else
10585         {
10586                 for (i = 0;i < texturenumsurfaces;i++)
10587                 {
10588                         surface = texturesurfacelist[i];
10589                         RSurf_BindLightmapForSurface(surface);
10590                         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);
10591                 }
10592         }
10593 }
10594
10595 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10596 {
10597         int j;
10598         int texturesurfaceindex;
10599         if (r_showsurfaces.integer == 2)
10600         {
10601                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10602                 {
10603                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10604                         for (j = 0;j < surface->num_triangles;j++)
10605                         {
10606                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
10607                                 GL_Color(f, f, f, 1);
10608                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10609                         }
10610                 }
10611         }
10612         else
10613         {
10614                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10615                 {
10616                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10617                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
10618                         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);
10619                         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);
10620                 }
10621         }
10622 }
10623
10624 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10625 {
10626         int texturesurfaceindex;
10627         int i;
10628         const float *v;
10629         float *c2;
10630         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10631         {
10632                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10633                 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)
10634                 {
10635                         c2[0] = 0.5;
10636                         c2[1] = 0.5;
10637                         c2[2] = 0.5;
10638                         c2[3] = 1;
10639                 }
10640         }
10641         rsurface.lightmapcolor4f = rsurface.array_color4f;
10642         rsurface.lightmapcolor4f_bufferobject = 0;
10643         rsurface.lightmapcolor4f_bufferoffset = 0;
10644 }
10645
10646 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10647 {
10648         int texturesurfaceindex;
10649         int i;
10650         float f;
10651         const float *v;
10652         const float *c;
10653         float *c2;
10654         if (rsurface.lightmapcolor4f)
10655         {
10656                 // generate color arrays for the surfaces in this list
10657                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10658                 {
10659                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10660                         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)
10661                         {
10662                                 f = RSurf_FogVertex(v);
10663                                 c2[0] = c[0] * f;
10664                                 c2[1] = c[1] * f;
10665                                 c2[2] = c[2] * f;
10666                                 c2[3] = c[3];
10667                         }
10668                 }
10669         }
10670         else
10671         {
10672                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10673                 {
10674                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10675                         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)
10676                         {
10677                                 f = RSurf_FogVertex(v);
10678                                 c2[0] = f;
10679                                 c2[1] = f;
10680                                 c2[2] = f;
10681                                 c2[3] = 1;
10682                         }
10683                 }
10684         }
10685         rsurface.lightmapcolor4f = rsurface.array_color4f;
10686         rsurface.lightmapcolor4f_bufferobject = 0;
10687         rsurface.lightmapcolor4f_bufferoffset = 0;
10688 }
10689
10690 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10691 {
10692         int texturesurfaceindex;
10693         int i;
10694         float f;
10695         const float *v;
10696         const float *c;
10697         float *c2;
10698         if (!rsurface.lightmapcolor4f)
10699                 return;
10700         // generate color arrays for the surfaces in this list
10701         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10702         {
10703                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10704                 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)
10705                 {
10706                         f = RSurf_FogVertex(v);
10707                         c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10708                         c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10709                         c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10710                         c2[3] = c[3];
10711                 }
10712         }
10713         rsurface.lightmapcolor4f = rsurface.array_color4f;
10714         rsurface.lightmapcolor4f_bufferobject = 0;
10715         rsurface.lightmapcolor4f_bufferoffset = 0;
10716 }
10717
10718 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
10719 {
10720         int texturesurfaceindex;
10721         int i;
10722         const float *c;
10723         float *c2;
10724         if (!rsurface.lightmapcolor4f)
10725                 return;
10726         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10727         {
10728                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10729                 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)
10730                 {
10731                         c2[0] = c[0] * r;
10732                         c2[1] = c[1] * g;
10733                         c2[2] = c[2] * b;
10734                         c2[3] = c[3] * a;
10735                 }
10736         }
10737         rsurface.lightmapcolor4f = rsurface.array_color4f;
10738         rsurface.lightmapcolor4f_bufferobject = 0;
10739         rsurface.lightmapcolor4f_bufferoffset = 0;
10740 }
10741
10742 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10743 {
10744         int texturesurfaceindex;
10745         int i;
10746         const float *c;
10747         float *c2;
10748         if (!rsurface.lightmapcolor4f)
10749                 return;
10750         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10751         {
10752                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10753                 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)
10754                 {
10755                         c2[0] = c[0] + r_refdef.scene.ambient;
10756                         c2[1] = c[1] + r_refdef.scene.ambient;
10757                         c2[2] = c[2] + r_refdef.scene.ambient;
10758                         c2[3] = c[3];
10759                 }
10760         }
10761         rsurface.lightmapcolor4f = rsurface.array_color4f;
10762         rsurface.lightmapcolor4f_bufferobject = 0;
10763         rsurface.lightmapcolor4f_bufferoffset = 0;
10764 }
10765
10766 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10767 {
10768         // TODO: optimize
10769         rsurface.lightmapcolor4f = NULL;
10770         rsurface.lightmapcolor4f_bufferobject = 0;
10771         rsurface.lightmapcolor4f_bufferoffset = 0;
10772         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10773         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10774         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10775         GL_Color(r, g, b, a);
10776         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10777 }
10778
10779 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10780 {
10781         // TODO: optimize applyfog && applycolor case
10782         // just apply fog if necessary, and tint the fog color array if necessary
10783         rsurface.lightmapcolor4f = NULL;
10784         rsurface.lightmapcolor4f_bufferobject = 0;
10785         rsurface.lightmapcolor4f_bufferoffset = 0;
10786         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10787         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10788         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10789         GL_Color(r, g, b, a);
10790         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10791 }
10792
10793 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10794 {
10795         int texturesurfaceindex;
10796         int i;
10797         float *c;
10798         // TODO: optimize
10799         if (texturesurfacelist[0]->lightmapinfo)
10800         {
10801                 // generate color arrays for the surfaces in this list
10802                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10803                 {
10804                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10805                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
10806                         {
10807                                 if (surface->lightmapinfo->samples)
10808                                 {
10809                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
10810                                         float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
10811                                         VectorScale(lm, scale, c);
10812                                         if (surface->lightmapinfo->styles[1] != 255)
10813                                         {
10814                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
10815                                                 lm += size3;
10816                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
10817                                                 VectorMA(c, scale, lm, c);
10818                                                 if (surface->lightmapinfo->styles[2] != 255)
10819                                                 {
10820                                                         lm += size3;
10821                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
10822                                                         VectorMA(c, scale, lm, c);
10823                                                         if (surface->lightmapinfo->styles[3] != 255)
10824                                                         {
10825                                                                 lm += size3;
10826                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
10827                                                                 VectorMA(c, scale, lm, c);
10828                                                         }
10829                                                 }
10830                                         }
10831                                 }
10832                                 else
10833                                         VectorClear(c);
10834                                 c[3] = 1;
10835                         }
10836                 }
10837                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10838                 rsurface.lightmapcolor4f_bufferobject = 0;
10839                 rsurface.lightmapcolor4f_bufferoffset = 0;
10840         }
10841         else
10842         {
10843                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10844                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10845                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10846         }
10847         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10848         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10849         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10850         GL_Color(r, g, b, a);
10851         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10852 }
10853
10854 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
10855 {
10856         int texturesurfaceindex;
10857         int i;
10858         float f;
10859         float alpha;
10860         const float *v;
10861         const float *n;
10862         float *c;
10863         vec3_t ambientcolor;
10864         vec3_t diffusecolor;
10865         vec3_t lightdir;
10866         // TODO: optimize
10867         // model lighting
10868         VectorCopy(rsurface.modellight_lightdir, lightdir);
10869         f = 0.5f * r_refdef.lightmapintensity;
10870         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10871         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10872         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10873         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10874         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10875         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10876         alpha = *a;
10877         if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
10878         {
10879                 // generate color arrays for the surfaces in this list
10880                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10881                 {
10882                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10883                         int numverts = surface->num_vertices;
10884                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
10885                         n = rsurface.normal3f + 3 * surface->num_firstvertex;
10886                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
10887                         // q3-style directional shading
10888                         for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
10889                         {
10890                                 if ((f = DotProduct(n, lightdir)) > 0)
10891                                         VectorMA(ambientcolor, f, diffusecolor, c);
10892                                 else
10893                                         VectorCopy(ambientcolor, c);
10894                                 c[3] = alpha;
10895                         }
10896                 }
10897                 *r = 1;
10898                 *g = 1;
10899                 *b = 1;
10900                 *a = 1;
10901                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10902                 rsurface.lightmapcolor4f_bufferobject = 0;
10903                 rsurface.lightmapcolor4f_bufferoffset = 0;
10904                 *applycolor = false;
10905         }
10906         else
10907         {
10908                 *r = ambientcolor[0];
10909                 *g = ambientcolor[1];
10910                 *b = ambientcolor[2];
10911                 rsurface.lightmapcolor4f = NULL;
10912                 rsurface.lightmapcolor4f_bufferobject = 0;
10913                 rsurface.lightmapcolor4f_bufferoffset = 0;
10914         }
10915 }
10916
10917 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10918 {
10919         RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
10920         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10921         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10922         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10923         GL_Color(r, g, b, a);
10924         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10925 }
10926
10927 void RSurf_SetupDepthAndCulling(void)
10928 {
10929         // submodels are biased to avoid z-fighting with world surfaces that they
10930         // may be exactly overlapping (avoids z-fighting artifacts on certain
10931         // doors and things in Quake maps)
10932         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10933         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10934         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10935         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10936 }
10937
10938 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10939 {
10940         // transparent sky would be ridiculous
10941         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10942                 return;
10943         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10944         skyrenderlater = true;
10945         RSurf_SetupDepthAndCulling();
10946         GL_DepthMask(true);
10947         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10948         // skymasking on them, and Quake3 never did sky masking (unlike
10949         // software Quake and software Quake2), so disable the sky masking
10950         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10951         // and skymasking also looks very bad when noclipping outside the
10952         // level, so don't use it then either.
10953         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
10954         {
10955                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10956                 R_Mesh_ColorPointer(NULL, 0, 0);
10957                 R_Mesh_ResetTextureState();
10958                 if (skyrendermasked)
10959                 {
10960                         R_SetupShader_DepthOrShadow();
10961                         // depth-only (masking)
10962                         GL_ColorMask(0,0,0,0);
10963                         // just to make sure that braindead drivers don't draw
10964                         // anything despite that colormask...
10965                         GL_BlendFunc(GL_ZERO, GL_ONE);
10966                 }
10967                 else
10968                 {
10969                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10970                         // fog sky
10971                         GL_BlendFunc(GL_ONE, GL_ZERO);
10972                 }
10973                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10974                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10975                 if (skyrendermasked)
10976                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10977         }
10978         R_Mesh_ResetTextureState();
10979         GL_Color(1, 1, 1, 1);
10980 }
10981
10982 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10983 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10984 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10985 {
10986         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10987                 return;
10988         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10989         if (prepass)
10990         {
10991                 // render screenspace normalmap to texture
10992                 GL_DepthMask(true);
10993                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY);
10994                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10995         }
10996         else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
10997         {
10998                 // render water or distortion background, then blend surface on top
10999                 GL_DepthMask(true);
11000                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
11001                 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
11002                 GL_DepthMask(false);
11003                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
11004                 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
11005                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
11006                 else
11007                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11008         }
11009         else
11010         {
11011                 // render surface normally
11012                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
11013                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
11014                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
11015                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
11016                 else if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
11017                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
11018                 else
11019                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11020         }
11021 }
11022
11023 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11024 {
11025         // OpenGL 1.3 path - anything not completely ancient
11026         int texturesurfaceindex;
11027         qboolean applycolor;
11028         qboolean applyfog;
11029         int layerindex;
11030         const texturelayer_t *layer;
11031         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
11032
11033         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
11034         {
11035                 vec4_t layercolor;
11036                 int layertexrgbscale;
11037                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11038                 {
11039                         if (layerindex == 0)
11040                                 GL_AlphaTest(true);
11041                         else
11042                         {
11043                                 GL_AlphaTest(false);
11044                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
11045                         }
11046                 }
11047                 GL_DepthMask(layer->depthmask && writedepth);
11048                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
11049                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
11050                 {
11051                         layertexrgbscale = 4;
11052                         VectorScale(layer->color, 0.25f, layercolor);
11053                 }
11054                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
11055                 {
11056                         layertexrgbscale = 2;
11057                         VectorScale(layer->color, 0.5f, layercolor);
11058                 }
11059                 else
11060                 {
11061                         layertexrgbscale = 1;
11062                         VectorScale(layer->color, 1.0f, layercolor);
11063                 }
11064                 layercolor[3] = layer->color[3];
11065                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
11066                 R_Mesh_ColorPointer(NULL, 0, 0);
11067                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
11068                 switch (layer->type)
11069                 {
11070                 case TEXTURELAYERTYPE_LITTEXTURE:
11071                         // single-pass lightmapped texture with 2x rgbscale
11072                         R_Mesh_TexBind(0, r_texture_white);
11073                         R_Mesh_TexMatrix(0, NULL);
11074                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11075                         R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
11076                         R_Mesh_TexBind(1, layer->texture);
11077                         R_Mesh_TexMatrix(1, &layer->texmatrix);
11078                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11079                         R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11080                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11081                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11082                         else if (rsurface.uselightmaptexture)
11083                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11084                         else
11085                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11086                         break;
11087                 case TEXTURELAYERTYPE_TEXTURE:
11088                         // singletexture unlit texture with transparency support
11089                         R_Mesh_TexBind(0, layer->texture);
11090                         R_Mesh_TexMatrix(0, &layer->texmatrix);
11091                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11092                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11093                         R_Mesh_TexBind(1, 0);
11094                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
11095                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11096                         break;
11097                 case TEXTURELAYERTYPE_FOG:
11098                         // singletexture fogging
11099                         if (layer->texture)
11100                         {
11101                                 R_Mesh_TexBind(0, layer->texture);
11102                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11103                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11104                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11105                         }
11106                         else
11107                         {
11108                                 R_Mesh_TexBind(0, 0);
11109                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
11110                         }
11111                         R_Mesh_TexBind(1, 0);
11112                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
11113                         // generate a color array for the fog pass
11114                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
11115                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11116                         {
11117                                 int i;
11118                                 float f;
11119                                 const float *v;
11120                                 float *c;
11121                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11122                                 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)
11123                                 {
11124                                         f = 1 - RSurf_FogVertex(v);
11125                                         c[0] = layercolor[0];
11126                                         c[1] = layercolor[1];
11127                                         c[2] = layercolor[2];
11128                                         c[3] = f * layercolor[3];
11129                                 }
11130                         }
11131                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11132                         break;
11133                 default:
11134                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11135                 }
11136         }
11137         CHECKGLERROR
11138         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11139         {
11140                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
11141                 GL_AlphaTest(false);
11142         }
11143 }
11144
11145 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11146 {
11147         // OpenGL 1.1 - crusty old voodoo path
11148         int texturesurfaceindex;
11149         qboolean applyfog;
11150         int layerindex;
11151         const texturelayer_t *layer;
11152         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
11153
11154         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
11155         {
11156                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11157                 {
11158                         if (layerindex == 0)
11159                                 GL_AlphaTest(true);
11160                         else
11161                         {
11162                                 GL_AlphaTest(false);
11163                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
11164                         }
11165                 }
11166                 GL_DepthMask(layer->depthmask && writedepth);
11167                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
11168                 R_Mesh_ColorPointer(NULL, 0, 0);
11169                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
11170                 switch (layer->type)
11171                 {
11172                 case TEXTURELAYERTYPE_LITTEXTURE:
11173                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
11174                         {
11175                                 // two-pass lit texture with 2x rgbscale
11176                                 // first the lightmap pass
11177                                 R_Mesh_TexBind(0, r_texture_white);
11178                                 R_Mesh_TexMatrix(0, NULL);
11179                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11180                                 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
11181                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11182                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
11183                                 else if (rsurface.uselightmaptexture)
11184                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
11185                                 else
11186                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
11187                                 // then apply the texture to it
11188                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
11189                                 R_Mesh_TexBind(0, layer->texture);
11190                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11191                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11192                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11193                                 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);
11194                         }
11195                         else
11196                         {
11197                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
11198                                 R_Mesh_TexBind(0, layer->texture);
11199                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11200                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11201                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11202                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11203                                         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);
11204                                 else
11205                                         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);
11206                         }
11207                         break;
11208                 case TEXTURELAYERTYPE_TEXTURE:
11209                         // singletexture unlit texture with transparency support
11210                         R_Mesh_TexBind(0, layer->texture);
11211                         R_Mesh_TexMatrix(0, &layer->texmatrix);
11212                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11213                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11214                         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);
11215                         break;
11216                 case TEXTURELAYERTYPE_FOG:
11217                         // singletexture fogging
11218                         if (layer->texture)
11219                         {
11220                                 R_Mesh_TexBind(0, layer->texture);
11221                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11222                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11223                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11224                         }
11225                         else
11226                         {
11227                                 R_Mesh_TexBind(0, 0);
11228                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
11229                         }
11230                         // generate a color array for the fog pass
11231                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
11232                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11233                         {
11234                                 int i;
11235                                 float f;
11236                                 const float *v;
11237                                 float *c;
11238                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11239                                 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)
11240                                 {
11241                                         f = 1 - RSurf_FogVertex(v);
11242                                         c[0] = layer->color[0];
11243                                         c[1] = layer->color[1];
11244                                         c[2] = layer->color[2];
11245                                         c[3] = f * layer->color[3];
11246                                 }
11247                         }
11248                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11249                         break;
11250                 default:
11251                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11252                 }
11253         }
11254         CHECKGLERROR
11255         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11256         {
11257                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
11258                 GL_AlphaTest(false);
11259         }
11260 }
11261
11262 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11263 {
11264         float c[4];
11265
11266         GL_AlphaTest(false);
11267         R_Mesh_ColorPointer(NULL, 0, 0);
11268         R_Mesh_ResetTextureState();
11269         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11270
11271         if(rsurface.texture && rsurface.texture->currentskinframe)
11272         {
11273                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11274                 c[3] *= rsurface.texture->currentalpha;
11275         }
11276         else
11277         {
11278                 c[0] = 1;
11279                 c[1] = 0;
11280                 c[2] = 1;
11281                 c[3] = 1;
11282         }
11283
11284         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11285         {
11286                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11287                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11288                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11289         }
11290
11291         // brighten it up (as texture value 127 means "unlit")
11292         c[0] *= 2 * r_refdef.view.colorscale;
11293         c[1] *= 2 * r_refdef.view.colorscale;
11294         c[2] *= 2 * r_refdef.view.colorscale;
11295
11296         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11297                 c[3] *= r_wateralpha.value;
11298
11299         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11300         {
11301                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11302                 GL_DepthMask(false);
11303         }
11304         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11305         {
11306                 GL_BlendFunc(GL_ONE, GL_ONE);
11307                 GL_DepthMask(false);
11308         }
11309         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11310         {
11311                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11312                 GL_DepthMask(false);
11313         }
11314         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11315         {
11316                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11317                 GL_DepthMask(false);
11318         }
11319         else
11320         {
11321                 GL_BlendFunc(GL_ONE, GL_ZERO);
11322                 GL_DepthMask(writedepth);
11323         }
11324
11325         rsurface.lightmapcolor4f = NULL;
11326
11327         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11328         {
11329                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11330
11331                 rsurface.lightmapcolor4f = NULL;
11332                 rsurface.lightmapcolor4f_bufferobject = 0;
11333                 rsurface.lightmapcolor4f_bufferoffset = 0;
11334         }
11335         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11336         {
11337                 qboolean applycolor = true;
11338                 float one = 1.0;
11339
11340                 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
11341
11342                 r_refdef.lightmapintensity = 1;
11343                 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
11344                 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11345         }
11346         else
11347         {
11348                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11349
11350                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
11351                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
11352                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11353         }
11354
11355         if(!rsurface.lightmapcolor4f)
11356                 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
11357
11358         RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
11359         RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
11360         if(r_refdef.fogenabled)
11361                 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
11362
11363         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
11364         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11365 }
11366
11367 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11368 {
11369         CHECKGLERROR
11370         RSurf_SetupDepthAndCulling();
11371         if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
11372         {
11373                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
11374                 return;
11375         }
11376         switch (vid.renderpath)
11377         {
11378         case RENDERPATH_GL20:
11379         case RENDERPATH_CGGL:
11380                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11381                 break;
11382         case RENDERPATH_GL13:
11383                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11384                 break;
11385         case RENDERPATH_GL11:
11386                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11387                 break;
11388         }
11389         CHECKGLERROR
11390 }
11391
11392 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11393 {
11394         CHECKGLERROR
11395         RSurf_SetupDepthAndCulling();
11396         if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
11397         {
11398                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
11399                 return;
11400         }
11401         switch (vid.renderpath)
11402         {
11403         case RENDERPATH_GL20:
11404         case RENDERPATH_CGGL:
11405                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11406                 break;
11407         case RENDERPATH_GL13:
11408                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11409                 break;
11410         case RENDERPATH_GL11:
11411                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11412                 break;
11413         }
11414         CHECKGLERROR
11415 }
11416
11417 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11418 {
11419         int i, j;
11420         int texturenumsurfaces, endsurface;
11421         texture_t *texture;
11422         const msurface_t *surface;
11423 #define MAXBATCH_TRANSPARENTSURFACES 256
11424         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
11425
11426         // if the model is static it doesn't matter what value we give for
11427         // wantnormals and wanttangents, so this logic uses only rules applicable
11428         // to a model, knowing that they are meaningless otherwise
11429         if (ent == r_refdef.scene.worldentity)
11430                 RSurf_ActiveWorldEntity();
11431         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11432                 RSurf_ActiveModelEntity(ent, false, false, false);
11433         else
11434         {
11435                 switch (vid.renderpath)
11436                 {
11437                 case RENDERPATH_GL20:
11438                 case RENDERPATH_CGGL:
11439                         RSurf_ActiveModelEntity(ent, true, true, false);
11440                         break;
11441                 case RENDERPATH_GL13:
11442                 case RENDERPATH_GL11:
11443                         RSurf_ActiveModelEntity(ent, true, false, false);
11444                         break;
11445                 }
11446         }
11447
11448         if (r_transparentdepthmasking.integer)
11449         {
11450                 qboolean setup = false;
11451                 for (i = 0;i < numsurfaces;i = j)
11452                 {
11453                         j = i + 1;
11454                         surface = rsurface.modelsurfaces + surfacelist[i];
11455                         texture = surface->texture;
11456                         rsurface.texture = R_GetCurrentTexture(texture);
11457                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11458                         // scan ahead until we find a different texture
11459                         endsurface = min(i + 1024, numsurfaces);
11460                         texturenumsurfaces = 0;
11461                         texturesurfacelist[texturenumsurfaces++] = surface;
11462                         for (;j < endsurface;j++)
11463                         {
11464                                 surface = rsurface.modelsurfaces + surfacelist[j];
11465                                 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
11466                                         break;
11467                                 texturesurfacelist[texturenumsurfaces++] = surface;
11468                         }
11469                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11470                                 continue;
11471                         // render the range of surfaces as depth
11472                         if (!setup)
11473                         {
11474                                 setup = true;
11475                                 GL_ColorMask(0,0,0,0);
11476                                 GL_Color(1,1,1,1);
11477                                 GL_DepthTest(true);
11478                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11479                                 GL_DepthMask(true);
11480                                 GL_AlphaTest(false);
11481                                 R_Mesh_ColorPointer(NULL, 0, 0);
11482                                 R_Mesh_ResetTextureState();
11483                                 R_SetupShader_DepthOrShadow();
11484                         }
11485                         RSurf_SetupDepthAndCulling();
11486                         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11487                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11488                 }
11489                 if (setup)
11490                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11491         }
11492
11493         for (i = 0;i < numsurfaces;i = j)
11494         {
11495                 j = i + 1;
11496                 surface = rsurface.modelsurfaces + surfacelist[i];
11497                 texture = surface->texture;
11498                 rsurface.texture = R_GetCurrentTexture(texture);
11499                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11500                 // scan ahead until we find a different texture
11501                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
11502                 texturenumsurfaces = 0;
11503                 texturesurfacelist[texturenumsurfaces++] = surface;
11504                 for (;j < endsurface;j++)
11505                 {
11506                         surface = rsurface.modelsurfaces + surfacelist[j];
11507                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
11508                                 break;
11509                         texturesurfacelist[texturenumsurfaces++] = surface;
11510                 }
11511                 // render the range of surfaces
11512                 if (ent == r_refdef.scene.worldentity)
11513                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11514                 else
11515                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11516         }
11517         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11518         GL_AlphaTest(false);
11519 }
11520
11521 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
11522 {
11523         // transparent surfaces get pushed off into the transparent queue
11524         int surfacelistindex;
11525         const msurface_t *surface;
11526         vec3_t tempcenter, center;
11527         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11528         {
11529                 surface = texturesurfacelist[surfacelistindex];
11530                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11531                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11532                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11533                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11534                 if (queueentity->transparent_offset) // transparent offset
11535                 {
11536                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
11537                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
11538                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
11539                 }
11540                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
11541         }
11542 }
11543
11544 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11545 {
11546         const entity_render_t *queueentity = r_refdef.scene.worldentity;
11547         CHECKGLERROR
11548         if (depthonly)
11549         {
11550                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11551                         return;
11552                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11553                         return;
11554                 RSurf_SetupDepthAndCulling();
11555                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11556                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11557         }
11558         else if (prepass)
11559         {
11560                 if (!rsurface.texture->currentnumlayers)
11561                         return;
11562                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11563                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11564                 else
11565                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11566         }
11567         else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
11568         {
11569                 RSurf_SetupDepthAndCulling();
11570                 GL_AlphaTest(false);
11571                 R_Mesh_ColorPointer(NULL, 0, 0);
11572                 R_Mesh_ResetTextureState();
11573                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11574                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11575                 GL_DepthMask(true);
11576                 GL_BlendFunc(GL_ONE, GL_ZERO);
11577                 GL_Color(0, 0, 0, 1);
11578                 GL_DepthTest(writedepth);
11579                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11580         }
11581         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
11582         {
11583                 RSurf_SetupDepthAndCulling();
11584                 GL_AlphaTest(false);
11585                 R_Mesh_ColorPointer(NULL, 0, 0);
11586                 R_Mesh_ResetTextureState();
11587                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11588                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11589                 GL_DepthMask(true);
11590                 GL_BlendFunc(GL_ONE, GL_ZERO);
11591                 GL_DepthTest(true);
11592                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11593         }
11594         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11595                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11596         else if (!rsurface.texture->currentnumlayers)
11597                 return;
11598         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11599         {
11600                 // in the deferred case, transparent surfaces were queued during prepass
11601                 if (!r_shadow_usingdeferredprepass)
11602                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11603         }
11604         else
11605         {
11606                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11607                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11608         }
11609         CHECKGLERROR
11610 }
11611
11612 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11613 {
11614         int i, j;
11615         texture_t *texture;
11616         // break the surface list down into batches by texture and use of lightmapping
11617         for (i = 0;i < numsurfaces;i = j)
11618         {
11619                 j = i + 1;
11620                 // texture is the base texture pointer, rsurface.texture is the
11621                 // current frame/skin the texture is directing us to use (for example
11622                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11623                 // use skin 1 instead)
11624                 texture = surfacelist[i]->texture;
11625                 rsurface.texture = R_GetCurrentTexture(texture);
11626                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11627                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11628                 {
11629                         // if this texture is not the kind we want, skip ahead to the next one
11630                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11631                                 ;
11632                         continue;
11633                 }
11634                 // simply scan ahead until we find a different texture or lightmap state
11635                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11636                         ;
11637                 // render the range of surfaces
11638                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11639         }
11640 }
11641
11642 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
11643 {
11644         CHECKGLERROR
11645         if (depthonly)
11646         {
11647                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11648                         return;
11649                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11650                         return;
11651                 RSurf_SetupDepthAndCulling();
11652                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11653                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11654         }
11655         else if (prepass)
11656         {
11657                 if (!rsurface.texture->currentnumlayers)
11658                         return;
11659                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11660                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11661                 else
11662                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11663         }
11664         else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
11665         {
11666                 RSurf_SetupDepthAndCulling();
11667                 GL_AlphaTest(false);
11668                 R_Mesh_ColorPointer(NULL, 0, 0);
11669                 R_Mesh_ResetTextureState();
11670                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11671                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11672                 GL_DepthMask(true);
11673                 GL_BlendFunc(GL_ONE, GL_ZERO);
11674                 GL_Color(0, 0, 0, 1);
11675                 GL_DepthTest(writedepth);
11676                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11677         }
11678         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11679         {
11680                 RSurf_SetupDepthAndCulling();
11681                 GL_AlphaTest(false);
11682                 R_Mesh_ColorPointer(NULL, 0, 0);
11683                 R_Mesh_ResetTextureState();
11684                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11685                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11686                 GL_DepthMask(true);
11687                 GL_BlendFunc(GL_ONE, GL_ZERO);
11688                 GL_DepthTest(true);
11689                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11690         }
11691         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11692                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11693         else if (!rsurface.texture->currentnumlayers)
11694                 return;
11695         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11696         {
11697                 // in the deferred case, transparent surfaces were queued during prepass
11698                 if (!r_shadow_usingdeferredprepass)
11699                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11700         }
11701         else
11702         {
11703                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11704                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11705         }
11706         CHECKGLERROR
11707 }
11708
11709 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11710 {
11711         int i, j;
11712         texture_t *texture;
11713         // break the surface list down into batches by texture and use of lightmapping
11714         for (i = 0;i < numsurfaces;i = j)
11715         {
11716                 j = i + 1;
11717                 // texture is the base texture pointer, rsurface.texture is the
11718                 // current frame/skin the texture is directing us to use (for example
11719                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11720                 // use skin 1 instead)
11721                 texture = surfacelist[i]->texture;
11722                 rsurface.texture = R_GetCurrentTexture(texture);
11723                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11724                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11725                 {
11726                         // if this texture is not the kind we want, skip ahead to the next one
11727                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11728                                 ;
11729                         continue;
11730                 }
11731                 // simply scan ahead until we find a different texture or lightmap state
11732                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11733                         ;
11734                 // render the range of surfaces
11735                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
11736         }
11737 }
11738
11739 float locboxvertex3f[6*4*3] =
11740 {
11741         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11742         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11743         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11744         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11745         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11746         1,0,0, 0,0,0, 0,1,0, 1,1,0
11747 };
11748
11749 unsigned short locboxelements[6*2*3] =
11750 {
11751          0, 1, 2, 0, 2, 3,
11752          4, 5, 6, 4, 6, 7,
11753          8, 9,10, 8,10,11,
11754         12,13,14, 12,14,15,
11755         16,17,18, 16,18,19,
11756         20,21,22, 20,22,23
11757 };
11758
11759 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11760 {
11761         int i, j;
11762         cl_locnode_t *loc = (cl_locnode_t *)ent;
11763         vec3_t mins, size;
11764         float vertex3f[6*4*3];
11765         CHECKGLERROR
11766         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11767         GL_DepthMask(false);
11768         GL_DepthRange(0, 1);
11769         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11770         GL_DepthTest(true);
11771         GL_CullFace(GL_NONE);
11772         R_EntityMatrix(&identitymatrix);
11773
11774         R_Mesh_VertexPointer(vertex3f, 0, 0);
11775         R_Mesh_ColorPointer(NULL, 0, 0);
11776         R_Mesh_ResetTextureState();
11777         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11778
11779         i = surfacelist[0];
11780         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11781                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11782                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11783                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11784
11785         if (VectorCompare(loc->mins, loc->maxs))
11786         {
11787                 VectorSet(size, 2, 2, 2);
11788                 VectorMA(loc->mins, -0.5f, size, mins);
11789         }
11790         else
11791         {
11792                 VectorCopy(loc->mins, mins);
11793                 VectorSubtract(loc->maxs, loc->mins, size);
11794         }
11795
11796         for (i = 0;i < 6*4*3;)
11797                 for (j = 0;j < 3;j++, i++)
11798                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11799
11800         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
11801 }
11802
11803 void R_DrawLocs(void)
11804 {
11805         int index;
11806         cl_locnode_t *loc, *nearestloc;
11807         vec3_t center;
11808         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11809         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11810         {
11811                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11812                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11813         }
11814 }
11815
11816 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11817 {
11818         if (decalsystem->decals)
11819                 Mem_Free(decalsystem->decals);
11820         memset(decalsystem, 0, sizeof(*decalsystem));
11821 }
11822
11823 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)
11824 {
11825         tridecal_t *decal;
11826         tridecal_t *decals;
11827         int i;
11828
11829         // expand or initialize the system
11830         if (decalsystem->maxdecals <= decalsystem->numdecals)
11831         {
11832                 decalsystem_t old = *decalsystem;
11833                 qboolean useshortelements;
11834                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11835                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11836                 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)));
11837                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11838                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11839                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11840                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11841                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11842                 if (decalsystem->numdecals)
11843                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11844                 if (old.decals)
11845                         Mem_Free(old.decals);
11846                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11847                         decalsystem->element3i[i] = i;
11848                 if (useshortelements)
11849                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11850                                 decalsystem->element3s[i] = i;
11851         }
11852
11853         // grab a decal and search for another free slot for the next one
11854         decals = decalsystem->decals;
11855         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11856         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
11857                 ;
11858         decalsystem->freedecal = i;
11859         if (decalsystem->numdecals <= i)
11860                 decalsystem->numdecals = i + 1;
11861
11862         // initialize the decal
11863         decal->lived = 0;
11864         decal->triangleindex = triangleindex;
11865         decal->surfaceindex = surfaceindex;
11866         decal->decalsequence = decalsequence;
11867         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
11868         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
11869         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
11870         decal->color4ub[0][3] = 255;
11871         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
11872         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
11873         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
11874         decal->color4ub[1][3] = 255;
11875         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
11876         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
11877         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
11878         decal->color4ub[2][3] = 255;
11879         decal->vertex3f[0][0] = v0[0];
11880         decal->vertex3f[0][1] = v0[1];
11881         decal->vertex3f[0][2] = v0[2];
11882         decal->vertex3f[1][0] = v1[0];
11883         decal->vertex3f[1][1] = v1[1];
11884         decal->vertex3f[1][2] = v1[2];
11885         decal->vertex3f[2][0] = v2[0];
11886         decal->vertex3f[2][1] = v2[1];
11887         decal->vertex3f[2][2] = v2[2];
11888         decal->texcoord2f[0][0] = t0[0];
11889         decal->texcoord2f[0][1] = t0[1];
11890         decal->texcoord2f[1][0] = t1[0];
11891         decal->texcoord2f[1][1] = t1[1];
11892         decal->texcoord2f[2][0] = t2[0];
11893         decal->texcoord2f[2][1] = t2[1];
11894 }
11895
11896 extern cvar_t cl_decals_bias;
11897 extern cvar_t cl_decals_models;
11898 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11899 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)
11900 {
11901         matrix4x4_t projection;
11902         decalsystem_t *decalsystem;
11903         qboolean dynamic;
11904         dp_model_t *model;
11905         const float *vertex3f;
11906         const msurface_t *surface;
11907         const msurface_t *surfaces;
11908         const int *surfacelist;
11909         const texture_t *texture;
11910         int numtriangles;
11911         int numsurfacelist;
11912         int surfacelistindex;
11913         int surfaceindex;
11914         int triangleindex;
11915         int cornerindex;
11916         int index;
11917         int numpoints;
11918         const int *e;
11919         float localorigin[3];
11920         float localnormal[3];
11921         float localmins[3];
11922         float localmaxs[3];
11923         float localsize;
11924         float v[9][3];
11925         float tc[9][2];
11926         float c[9][4];
11927         //float normal[3];
11928         float planes[6][4];
11929         float f;
11930         float points[2][9][3];
11931         float angles[3];
11932         float temp[3];
11933
11934         decalsystem = &ent->decalsystem;
11935         model = ent->model;
11936         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11937         {
11938                 R_DecalSystem_Reset(&ent->decalsystem);
11939                 return;
11940         }
11941
11942         if (!model->brush.data_nodes && !cl_decals_models.integer)
11943         {
11944                 if (decalsystem->model)
11945                         R_DecalSystem_Reset(decalsystem);
11946                 return;
11947         }
11948
11949         if (decalsystem->model != model)
11950                 R_DecalSystem_Reset(decalsystem);
11951         decalsystem->model = model;
11952
11953         RSurf_ActiveModelEntity(ent, false, false, false);
11954
11955         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11956         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11957         VectorNormalize(localnormal);
11958         localsize = worldsize*rsurface.inversematrixscale;
11959         localmins[0] = localorigin[0] - localsize;
11960         localmins[1] = localorigin[1] - localsize;
11961         localmins[2] = localorigin[2] - localsize;
11962         localmaxs[0] = localorigin[0] + localsize;
11963         localmaxs[1] = localorigin[1] + localsize;
11964         localmaxs[2] = localorigin[2] + localsize;
11965
11966         //VectorCopy(localnormal, planes[4]);
11967         //VectorVectors(planes[4], planes[2], planes[0]);
11968         AnglesFromVectors(angles, localnormal, NULL, false);
11969         AngleVectors(angles, planes[0], planes[2], planes[4]);
11970         VectorNegate(planes[0], planes[1]);
11971         VectorNegate(planes[2], planes[3]);
11972         VectorNegate(planes[4], planes[5]);
11973         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11974         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11975         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11976         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11977         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11978         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11979
11980 #if 1
11981 // works
11982 {
11983         matrix4x4_t forwardprojection;
11984         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11985         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11986 }
11987 #else
11988 // broken
11989 {
11990         float projectionvector[4][3];
11991         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11992         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11993         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11994         projectionvector[0][0] = planes[0][0] * ilocalsize;
11995         projectionvector[0][1] = planes[1][0] * ilocalsize;
11996         projectionvector[0][2] = planes[2][0] * ilocalsize;
11997         projectionvector[1][0] = planes[0][1] * ilocalsize;
11998         projectionvector[1][1] = planes[1][1] * ilocalsize;
11999         projectionvector[1][2] = planes[2][1] * ilocalsize;
12000         projectionvector[2][0] = planes[0][2] * ilocalsize;
12001         projectionvector[2][1] = planes[1][2] * ilocalsize;
12002         projectionvector[2][2] = planes[2][2] * ilocalsize;
12003         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
12004         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
12005         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
12006         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
12007 }
12008 #endif
12009
12010         dynamic = model->surfmesh.isanimated;
12011         vertex3f = rsurface.modelvertex3f;
12012         numsurfacelist = model->nummodelsurfaces;
12013         surfacelist = model->sortedmodelsurfaces;
12014         surfaces = model->data_surfaces;
12015         for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
12016         {
12017                 surfaceindex = surfacelist[surfacelistindex];
12018                 surface = surfaces + surfaceindex;
12019                 // check cull box first because it rejects more than any other check
12020                 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
12021                         continue;
12022                 // skip transparent surfaces
12023                 texture = surface->texture;
12024                 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12025                         continue;
12026                 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12027                         continue;
12028                 numtriangles = surface->num_triangles;
12029                 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
12030                 {
12031                         for (cornerindex = 0;cornerindex < 3;cornerindex++)
12032                         {
12033                                 index = 3*e[cornerindex];
12034                                 VectorCopy(vertex3f + index, v[cornerindex]);
12035                         }
12036                         // cull backfaces
12037                         //TriangleNormal(v[0], v[1], v[2], normal);
12038                         //if (DotProduct(normal, localnormal) < 0.0f)
12039                         //      continue;
12040                         // clip by each of the box planes formed from the projection matrix
12041                         // if anything survives, we emit the decal
12042                         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]);
12043                         if (numpoints < 3)
12044                                 continue;
12045                         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]);
12046                         if (numpoints < 3)
12047                                 continue;
12048                         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]);
12049                         if (numpoints < 3)
12050                                 continue;
12051                         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]);
12052                         if (numpoints < 3)
12053                                 continue;
12054                         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]);
12055                         if (numpoints < 3)
12056                                 continue;
12057                         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]);
12058                         if (numpoints < 3)
12059                                 continue;
12060                         // some part of the triangle survived, so we have to accept it...
12061                         if (dynamic)
12062                         {
12063                                 // dynamic always uses the original triangle
12064                                 numpoints = 3;
12065                                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
12066                                 {
12067                                         index = 3*e[cornerindex];
12068                                         VectorCopy(vertex3f + index, v[cornerindex]);
12069                                 }
12070                         }
12071                         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
12072                         {
12073                                 // convert vertex positions to texcoords
12074                                 Matrix4x4_Transform(&projection, v[cornerindex], temp);
12075                                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
12076                                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
12077                                 // calculate distance fade from the projection origin
12078                                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
12079                                 f = bound(0.0f, f, 1.0f);
12080                                 c[cornerindex][0] = r * f;
12081                                 c[cornerindex][1] = g * f;
12082                                 c[cornerindex][2] = b * f;
12083                                 c[cornerindex][3] = 1.0f;
12084                                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
12085                         }
12086                         if (dynamic)
12087                                 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);
12088                         else
12089                                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
12090                                         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);
12091                 }
12092         }
12093 }
12094
12095 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
12096 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)
12097 {
12098         int renderentityindex;
12099         float worldmins[3];
12100         float worldmaxs[3];
12101         entity_render_t *ent;
12102
12103         if (!cl_decals_newsystem.integer)
12104                 return;
12105
12106         worldmins[0] = worldorigin[0] - worldsize;
12107         worldmins[1] = worldorigin[1] - worldsize;
12108         worldmins[2] = worldorigin[2] - worldsize;
12109         worldmaxs[0] = worldorigin[0] + worldsize;
12110         worldmaxs[1] = worldorigin[1] + worldsize;
12111         worldmaxs[2] = worldorigin[2] + worldsize;
12112
12113         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12114
12115         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
12116         {
12117                 ent = r_refdef.scene.entities[renderentityindex];
12118                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
12119                         continue;
12120
12121                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12122         }
12123 }
12124
12125 typedef struct r_decalsystem_splatqueue_s
12126 {
12127         vec3_t worldorigin;
12128         vec3_t worldnormal;
12129         float color[4];
12130         float tcrange[4];
12131         float worldsize;
12132         int decalsequence;
12133 }
12134 r_decalsystem_splatqueue_t;
12135
12136 int r_decalsystem_numqueued = 0;
12137 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12138
12139 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)
12140 {
12141         r_decalsystem_splatqueue_t *queue;
12142
12143         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12144                 return;
12145
12146         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12147         VectorCopy(worldorigin, queue->worldorigin);
12148         VectorCopy(worldnormal, queue->worldnormal);
12149         Vector4Set(queue->color, r, g, b, a);
12150         Vector4Set(queue->tcrange, s1, t1, s2, t2);
12151         queue->worldsize = worldsize;
12152         queue->decalsequence = cl.decalsequence++;
12153 }
12154
12155 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12156 {
12157         int i;
12158         r_decalsystem_splatqueue_t *queue;
12159
12160         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12161                 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);
12162         r_decalsystem_numqueued = 0;
12163 }
12164
12165 extern cvar_t cl_decals_max;
12166 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12167 {
12168         int i;
12169         decalsystem_t *decalsystem = &ent->decalsystem;
12170         int numdecals;
12171         int killsequence;
12172         tridecal_t *decal;
12173         float frametime;
12174         float lifetime;
12175
12176         if (!decalsystem->numdecals)
12177                 return;
12178
12179         if (r_showsurfaces.integer)
12180                 return;
12181
12182         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12183         {
12184                 R_DecalSystem_Reset(decalsystem);
12185                 return;
12186         }
12187
12188         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
12189         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12190
12191         if (decalsystem->lastupdatetime)
12192                 frametime = (cl.time - decalsystem->lastupdatetime);
12193         else
12194                 frametime = 0;
12195         decalsystem->lastupdatetime = cl.time;
12196         decal = decalsystem->decals;
12197         numdecals = decalsystem->numdecals;
12198
12199         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12200         {
12201                 if (decal->color4ub[0][3])
12202                 {
12203                         decal->lived += frametime;
12204                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
12205                         {
12206                                 memset(decal, 0, sizeof(*decal));
12207                                 if (decalsystem->freedecal > i)
12208                                         decalsystem->freedecal = i;
12209                         }
12210                 }
12211         }
12212         decal = decalsystem->decals;
12213         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
12214                 numdecals--;
12215
12216         // collapse the array by shuffling the tail decals into the gaps
12217         for (;;)
12218         {
12219                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
12220                         decalsystem->freedecal++;
12221                 if (decalsystem->freedecal == numdecals)
12222                         break;
12223                 decal[decalsystem->freedecal] = decal[--numdecals];
12224         }
12225
12226         decalsystem->numdecals = numdecals;
12227
12228         if (numdecals <= 0)
12229         {
12230                 // if there are no decals left, reset decalsystem
12231                 R_DecalSystem_Reset(decalsystem);
12232         }
12233 }
12234
12235 extern skinframe_t *decalskinframe;
12236 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12237 {
12238         int i;
12239         decalsystem_t *decalsystem = &ent->decalsystem;
12240         int numdecals;
12241         tridecal_t *decal;
12242         float faderate;
12243         float alpha;
12244         float *v3f;
12245         float *c4f;
12246         float *t2f;
12247         const int *e;
12248         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12249         int numtris = 0;
12250
12251         numdecals = decalsystem->numdecals;
12252         if (!numdecals)
12253                 return;
12254
12255         if (r_showsurfaces.integer)
12256                 return;
12257
12258         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12259         {
12260                 R_DecalSystem_Reset(decalsystem);
12261                 return;
12262         }
12263
12264         // if the model is static it doesn't matter what value we give for
12265         // wantnormals and wanttangents, so this logic uses only rules applicable
12266         // to a model, knowing that they are meaningless otherwise
12267         if (ent == r_refdef.scene.worldentity)
12268                 RSurf_ActiveWorldEntity();
12269         else
12270                 RSurf_ActiveModelEntity(ent, false, false, false);
12271
12272         decalsystem->lastupdatetime = cl.time;
12273         decal = decalsystem->decals;
12274
12275         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12276
12277         // update vertex positions for animated models
12278         v3f = decalsystem->vertex3f;
12279         c4f = decalsystem->color4f;
12280         t2f = decalsystem->texcoord2f;
12281         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12282         {
12283                 if (!decal->color4ub[0][3])
12284                         continue;
12285
12286                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12287                         continue;
12288
12289                 // update color values for fading decals
12290                 if (decal->lived >= cl_decals_time.value)
12291                 {
12292                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12293                         alpha *= (1.0f/255.0f);
12294                 }
12295                 else
12296                         alpha = 1.0f/255.0f;
12297
12298                 c4f[ 0] = decal->color4ub[0][0] * alpha;
12299                 c4f[ 1] = decal->color4ub[0][1] * alpha;
12300                 c4f[ 2] = decal->color4ub[0][2] * alpha;
12301                 c4f[ 3] = 1;
12302                 c4f[ 4] = decal->color4ub[1][0] * alpha;
12303                 c4f[ 5] = decal->color4ub[1][1] * alpha;
12304                 c4f[ 6] = decal->color4ub[1][2] * alpha;
12305                 c4f[ 7] = 1;
12306                 c4f[ 8] = decal->color4ub[2][0] * alpha;
12307                 c4f[ 9] = decal->color4ub[2][1] * alpha;
12308                 c4f[10] = decal->color4ub[2][2] * alpha;
12309                 c4f[11] = 1;
12310
12311                 t2f[0] = decal->texcoord2f[0][0];
12312                 t2f[1] = decal->texcoord2f[0][1];
12313                 t2f[2] = decal->texcoord2f[1][0];
12314                 t2f[3] = decal->texcoord2f[1][1];
12315                 t2f[4] = decal->texcoord2f[2][0];
12316                 t2f[5] = decal->texcoord2f[2][1];
12317
12318                 // update vertex positions for animated models
12319                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
12320                 {
12321                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12322                         VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
12323                         VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
12324                         VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
12325                 }
12326                 else
12327                 {
12328                         VectorCopy(decal->vertex3f[0], v3f);
12329                         VectorCopy(decal->vertex3f[1], v3f + 3);
12330                         VectorCopy(decal->vertex3f[2], v3f + 6);
12331                 }
12332
12333                 if (r_refdef.fogenabled)
12334                 {
12335                         alpha = RSurf_FogVertex(v3f);
12336                         VectorScale(c4f, alpha, c4f);
12337                         alpha = RSurf_FogVertex(v3f + 3);
12338                         VectorScale(c4f + 4, alpha, c4f + 4);
12339                         alpha = RSurf_FogVertex(v3f + 6);
12340                         VectorScale(c4f + 8, alpha, c4f + 8);
12341                 }
12342
12343                 v3f += 9;
12344                 c4f += 12;
12345                 t2f += 6;
12346                 numtris++;
12347         }
12348
12349         if (numtris > 0)
12350         {
12351                 r_refdef.stats.drawndecals += numtris;
12352
12353                 // now render the decals all at once
12354                 // (this assumes they all use one particle font texture!)
12355                 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);
12356                 R_Mesh_ResetTextureState();
12357                 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
12358                 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
12359                 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
12360                 GL_DepthMask(false);
12361                 GL_DepthRange(0, 1);
12362                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12363                 GL_DepthTest(true);
12364                 GL_CullFace(GL_NONE);
12365                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12366                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
12367                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
12368         }
12369 }
12370
12371 static void R_DrawModelDecals(void)
12372 {
12373         int i, numdecals;
12374
12375         // fade faster when there are too many decals
12376         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12377         for (i = 0;i < r_refdef.scene.numentities;i++)
12378                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12379
12380         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12381         for (i = 0;i < r_refdef.scene.numentities;i++)
12382                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12383                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12384
12385         R_DecalSystem_ApplySplatEntitiesQueue();
12386
12387         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12388         for (i = 0;i < r_refdef.scene.numentities;i++)
12389                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12390
12391         r_refdef.stats.totaldecals += numdecals;
12392
12393         if (r_showsurfaces.integer)
12394                 return;
12395
12396         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12397
12398         for (i = 0;i < r_refdef.scene.numentities;i++)
12399         {
12400                 if (!r_refdef.viewcache.entityvisible[i])
12401                         continue;
12402                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12403                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12404         }
12405 }
12406
12407 extern cvar_t mod_collision_bih;
12408 void R_DrawDebugModel(void)
12409 {
12410         entity_render_t *ent = rsurface.entity;
12411         int i, j, k, l, flagsmask;
12412         const msurface_t *surface;
12413         dp_model_t *model = ent->model;
12414         vec3_t v;
12415
12416         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12417
12418         R_Mesh_ColorPointer(NULL, 0, 0);
12419         R_Mesh_ResetTextureState();
12420         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12421         GL_DepthRange(0, 1);
12422         GL_DepthTest(!r_showdisabledepthtest.integer);
12423         GL_DepthMask(false);
12424         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12425
12426         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12427         {
12428                 int triangleindex;
12429                 int bihleafindex;
12430                 qboolean cullbox = ent == r_refdef.scene.worldentity;
12431                 const q3mbrush_t *brush;
12432                 const bih_t *bih = &model->collision_bih;
12433                 const bih_leaf_t *bihleaf;
12434                 float vertex3f[3][3];
12435                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12436                 cullbox = false;
12437                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12438                 {
12439                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12440                                 continue;
12441                         switch (bihleaf->type)
12442                         {
12443                         case BIH_BRUSH:
12444                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12445                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12446                                 {
12447                                         R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
12448                                         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);
12449                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
12450                                 }
12451                                 break;
12452                         case BIH_COLLISIONTRIANGLE:
12453                                 triangleindex = bihleaf->itemindex;
12454                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12455                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12456                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12457                                 R_Mesh_VertexPointer(vertex3f[0], 0, 0);
12458                                 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);
12459                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, polygonelement3s, 0, 0);
12460                                 break;
12461                         case BIH_RENDERTRIANGLE:
12462                                 triangleindex = bihleaf->itemindex;
12463                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12464                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12465                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12466                                 R_Mesh_VertexPointer(vertex3f[0], 0, 0);
12467                                 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);
12468                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, polygonelement3s, 0, 0);
12469                                 break;
12470                         }
12471                 }
12472         }
12473
12474         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12475
12476         if (r_showtris.integer || r_shownormals.integer)
12477         {
12478                 if (r_showdisabledepthtest.integer)
12479                 {
12480                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12481                         GL_DepthMask(false);
12482                 }
12483                 else
12484                 {
12485                         GL_BlendFunc(GL_ONE, GL_ZERO);
12486                         GL_DepthMask(true);
12487                 }
12488                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12489                 {
12490                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12491                                 continue;
12492                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12493                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12494                         {
12495                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
12496                                 if (r_showtris.value > 0)
12497                                 {
12498                                         if (!rsurface.texture->currentlayers->depthmask)
12499                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12500                                         else if (ent == r_refdef.scene.worldentity)
12501                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12502                                         else
12503                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12504                                         R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
12505                                         R_Mesh_ColorPointer(NULL, 0, 0);
12506                                         R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
12507                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
12508                                         //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
12509                                         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);
12510                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
12511                                         CHECKGLERROR
12512                                 }
12513                                 if (r_shownormals.value < 0)
12514                                 {
12515                                         qglBegin(GL_LINES);
12516                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12517                                         {
12518                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
12519                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12520                                                 qglVertex3f(v[0], v[1], v[2]);
12521                                                 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
12522                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12523                                                 qglVertex3f(v[0], v[1], v[2]);
12524                                         }
12525                                         qglEnd();
12526                                         CHECKGLERROR
12527                                 }
12528                                 if (r_shownormals.value > 0)
12529                                 {
12530                                         qglBegin(GL_LINES);
12531                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12532                                         {
12533                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
12534                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12535                                                 qglVertex3f(v[0], v[1], v[2]);
12536                                                 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
12537                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12538                                                 qglVertex3f(v[0], v[1], v[2]);
12539                                         }
12540                                         qglEnd();
12541                                         CHECKGLERROR
12542                                         qglBegin(GL_LINES);
12543                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12544                                         {
12545                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
12546                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12547                                                 qglVertex3f(v[0], v[1], v[2]);
12548                                                 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
12549                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12550                                                 qglVertex3f(v[0], v[1], v[2]);
12551                                         }
12552                                         qglEnd();
12553                                         CHECKGLERROR
12554                                         qglBegin(GL_LINES);
12555                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12556                                         {
12557                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
12558                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12559                                                 qglVertex3f(v[0], v[1], v[2]);
12560                                                 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
12561                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12562                                                 qglVertex3f(v[0], v[1], v[2]);
12563                                         }
12564                                         qglEnd();
12565                                         CHECKGLERROR
12566                                 }
12567                         }
12568                 }
12569                 rsurface.texture = NULL;
12570         }
12571 }
12572
12573 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
12574 int r_maxsurfacelist = 0;
12575 const msurface_t **r_surfacelist = NULL;
12576 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12577 {
12578         int i, j, endj, flagsmask;
12579         dp_model_t *model = r_refdef.scene.worldmodel;
12580         msurface_t *surfaces;
12581         unsigned char *update;
12582         int numsurfacelist = 0;
12583         if (model == NULL)
12584                 return;
12585
12586         if (r_maxsurfacelist < model->num_surfaces)
12587         {
12588                 r_maxsurfacelist = model->num_surfaces;
12589                 if (r_surfacelist)
12590                         Mem_Free((msurface_t**)r_surfacelist);
12591                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12592         }
12593
12594         RSurf_ActiveWorldEntity();
12595
12596         surfaces = model->data_surfaces;
12597         update = model->brushq1.lightmapupdateflags;
12598
12599         // update light styles on this submodel
12600         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12601         {
12602                 model_brush_lightstyleinfo_t *style;
12603                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12604                 {
12605                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12606                         {
12607                                 int *list = style->surfacelist;
12608                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12609                                 for (j = 0;j < style->numsurfaces;j++)
12610                                         update[list[j]] = true;
12611                         }
12612                 }
12613         }
12614
12615         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12616
12617         if (debug)
12618         {
12619                 R_DrawDebugModel();
12620                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12621                 return;
12622         }
12623
12624         rsurface.uselightmaptexture = false;
12625         rsurface.texture = NULL;
12626         rsurface.rtlight = NULL;
12627         numsurfacelist = 0;
12628         // add visible surfaces to draw list
12629         for (i = 0;i < model->nummodelsurfaces;i++)
12630         {
12631                 j = model->sortedmodelsurfaces[i];
12632                 if (r_refdef.viewcache.world_surfacevisible[j])
12633                         r_surfacelist[numsurfacelist++] = surfaces + j;
12634         }
12635         // update lightmaps if needed
12636         if (model->brushq1.firstrender)
12637         {
12638                 model->brushq1.firstrender = false;
12639                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12640                         if (update[j])
12641                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12642         }
12643         else if (update)
12644         {
12645                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12646                         if (r_refdef.viewcache.world_surfacevisible[j])
12647                                 if (update[j])
12648                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12649         }
12650         // don't do anything if there were no surfaces
12651         if (!numsurfacelist)
12652         {
12653                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12654                 return;
12655         }
12656         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12657         GL_AlphaTest(false);
12658
12659         // add to stats if desired
12660         if (r_speeds.integer && !skysurfaces && !depthonly)
12661         {
12662                 r_refdef.stats.world_surfaces += numsurfacelist;
12663                 for (j = 0;j < numsurfacelist;j++)
12664                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
12665         }
12666
12667         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12668 }
12669
12670 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12671 {
12672         int i, j, endj, flagsmask;
12673         dp_model_t *model = ent->model;
12674         msurface_t *surfaces;
12675         unsigned char *update;
12676         int numsurfacelist = 0;
12677         if (model == NULL)
12678                 return;
12679
12680         if (r_maxsurfacelist < model->num_surfaces)
12681         {
12682                 r_maxsurfacelist = model->num_surfaces;
12683                 if (r_surfacelist)
12684                         Mem_Free((msurface_t **)r_surfacelist);
12685                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12686         }
12687
12688         // if the model is static it doesn't matter what value we give for
12689         // wantnormals and wanttangents, so this logic uses only rules applicable
12690         // to a model, knowing that they are meaningless otherwise
12691         if (ent == r_refdef.scene.worldentity)
12692                 RSurf_ActiveWorldEntity();
12693         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12694                 RSurf_ActiveModelEntity(ent, false, false, false);
12695         else if (prepass)
12696                 RSurf_ActiveModelEntity(ent, true, true, true);
12697         else if (depthonly)
12698         {
12699                 switch (vid.renderpath)
12700                 {
12701                 case RENDERPATH_GL20:
12702                 case RENDERPATH_CGGL:
12703                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12704                         break;
12705                 case RENDERPATH_GL13:
12706                 case RENDERPATH_GL11:
12707                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12708                         break;
12709                 }
12710         }
12711         else
12712         {
12713                 switch (vid.renderpath)
12714                 {
12715                 case RENDERPATH_GL20:
12716                 case RENDERPATH_CGGL:
12717                         RSurf_ActiveModelEntity(ent, true, true, false);
12718                         break;
12719                 case RENDERPATH_GL13:
12720                 case RENDERPATH_GL11:
12721                         RSurf_ActiveModelEntity(ent, true, false, false);
12722                         break;
12723                 }
12724         }
12725
12726         surfaces = model->data_surfaces;
12727         update = model->brushq1.lightmapupdateflags;
12728
12729         // update light styles
12730         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12731         {
12732                 model_brush_lightstyleinfo_t *style;
12733                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12734                 {
12735                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12736                         {
12737                                 int *list = style->surfacelist;
12738                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12739                                 for (j = 0;j < style->numsurfaces;j++)
12740                                         update[list[j]] = true;
12741                         }
12742                 }
12743         }
12744
12745         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12746
12747         if (debug)
12748         {
12749                 R_DrawDebugModel();
12750                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12751                 return;
12752         }
12753
12754         rsurface.uselightmaptexture = false;
12755         rsurface.texture = NULL;
12756         rsurface.rtlight = NULL;
12757         numsurfacelist = 0;
12758         // add visible surfaces to draw list
12759         for (i = 0;i < model->nummodelsurfaces;i++)
12760                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12761         // don't do anything if there were no surfaces
12762         if (!numsurfacelist)
12763         {
12764                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12765                 return;
12766         }
12767         // update lightmaps if needed
12768         if (update)
12769         {
12770                 int updated = 0;
12771                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12772                 {
12773                         if (update[j])
12774                         {
12775                                 updated++;
12776                                 R_BuildLightMap(ent, surfaces + j);
12777                         }
12778                 }
12779         }
12780         if (update)
12781                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12782                         if (update[j])
12783                                 R_BuildLightMap(ent, surfaces + j);
12784         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12785         GL_AlphaTest(false);
12786
12787         // add to stats if desired
12788         if (r_speeds.integer && !skysurfaces && !depthonly)
12789         {
12790                 r_refdef.stats.entities_surfaces += numsurfacelist;
12791                 for (j = 0;j < numsurfacelist;j++)
12792                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
12793         }
12794
12795         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12796 }
12797
12798 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12799 {
12800         static texture_t texture;
12801         static msurface_t surface;
12802         const msurface_t *surfacelist = &surface;
12803
12804         // fake enough texture and surface state to render this geometry
12805
12806         texture.update_lastrenderframe = -1; // regenerate this texture
12807         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12808         texture.currentskinframe = skinframe;
12809         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12810         texture.offsetmapping = OFFSETMAPPING_OFF;
12811         texture.offsetscale = 1;
12812         texture.specularscalemod = 1;
12813         texture.specularpowermod = 1;
12814
12815         surface.texture = &texture;
12816         surface.num_triangles = numtriangles;
12817         surface.num_firsttriangle = firsttriangle;
12818         surface.num_vertices = numvertices;
12819         surface.num_firstvertex = firstvertex;
12820
12821         // now render it
12822         rsurface.texture = R_GetCurrentTexture(surface.texture);
12823         rsurface.uselightmaptexture = false;
12824         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12825 }
12826
12827 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)
12828 {
12829         static msurface_t surface;
12830         const msurface_t *surfacelist = &surface;
12831
12832         // fake enough texture and surface state to render this geometry
12833
12834         surface.texture = texture;
12835         surface.num_triangles = numtriangles;
12836         surface.num_firsttriangle = firsttriangle;
12837         surface.num_vertices = numvertices;
12838         surface.num_firstvertex = firstvertex;
12839
12840         // now render it
12841         rsurface.texture = R_GetCurrentTexture(surface.texture);
12842         rsurface.uselightmaptexture = false;
12843         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12844 }