]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
magical instruction sequence that works on both GL_ARB_texture_gather and GL_AMD_text...
[divverent/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28
29 mempool_t *r_main_mempool;
30 rtexturepool_t *r_main_texturepool;
31
32 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
33
34 static qboolean r_loadnormalmap;
35 static qboolean r_loadgloss;
36 qboolean r_loadfog;
37 static qboolean r_loaddds;
38 static qboolean r_savedds;
39
40 //
41 // screen size info
42 //
43 r_refdef_t r_refdef;
44
45 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
46 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
47 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
48 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
49 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
50 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
51 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
52 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
53
54 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
55 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
56 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
57 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
58 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
59
60 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
61 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
62 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
63 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
64 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
65 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
66 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
67 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
68 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
69 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
70 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
71 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
72 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
73 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
74 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
75 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
76 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
77 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
78 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
79 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
80 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
81 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
82 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
83 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
84 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
85 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
86 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
87 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
88 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
89 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
90 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
91 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
92 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
93 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
94 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
95 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
96 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
97 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
98 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
99 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
100 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
101 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
102 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
103 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
104
105 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
106 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
107 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
108 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
109 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
110 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
111 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
112 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
113
114 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
115 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
116
117 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
118 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
119 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
120 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
121 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
122
123 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
124 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
125 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
126
127 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
128 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
129 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
130 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
131 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
132 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
133 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
134 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
135 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
136
137 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
138 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
139 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
140 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
141 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
142
143 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
144 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
145 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
146 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
147
148 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
149 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
150 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
151 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
152 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
153 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
154 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
155
156 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
157 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
158 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
159 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
160
161 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
162
163 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
164
165 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
166
167 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
168 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
169 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
170 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
171 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
172 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
173 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
174 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "16", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
175
176 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
177
178 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "1", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
179
180 extern cvar_t v_glslgamma;
181
182 extern qboolean v_flipped_state;
183
184 static struct r_bloomstate_s
185 {
186         qboolean enabled;
187         qboolean hdr;
188
189         int bloomwidth, bloomheight;
190
191         int screentexturewidth, screentextureheight;
192         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
193
194         int bloomtexturewidth, bloomtextureheight;
195         rtexture_t *texture_bloom;
196
197         // arrays for rendering the screen passes
198         float screentexcoord2f[8];
199         float bloomtexcoord2f[8];
200         float offsettexcoord2f[8];
201
202         r_viewport_t viewport;
203 }
204 r_bloomstate;
205
206 r_waterstate_t r_waterstate;
207
208 /// shadow volume bsp struct with automatically growing nodes buffer
209 svbsp_t r_svbsp;
210
211 rtexture_t *r_texture_blanknormalmap;
212 rtexture_t *r_texture_white;
213 rtexture_t *r_texture_grey128;
214 rtexture_t *r_texture_black;
215 rtexture_t *r_texture_notexture;
216 rtexture_t *r_texture_whitecube;
217 rtexture_t *r_texture_normalizationcube;
218 rtexture_t *r_texture_fogattenuation;
219 rtexture_t *r_texture_gammaramps;
220 unsigned int r_texture_gammaramps_serial;
221 //rtexture_t *r_texture_fogintensity;
222 rtexture_t *r_texture_reflectcube;
223
224 // TODO: hash lookups?
225 typedef struct cubemapinfo_s
226 {
227         char basename[64];
228         rtexture_t *texture;
229 }
230 cubemapinfo_t;
231
232 int r_texture_numcubemaps;
233 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
234
235 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
236 unsigned int r_numqueries;
237 unsigned int r_maxqueries;
238
239 typedef struct r_qwskincache_s
240 {
241         char name[MAX_QPATH];
242         skinframe_t *skinframe;
243 }
244 r_qwskincache_t;
245
246 static r_qwskincache_t *r_qwskincache;
247 static int r_qwskincache_size;
248
249 /// vertex coordinates for a quad that covers the screen exactly
250 const float r_screenvertex3f[12] =
251 {
252         0, 0, 0,
253         1, 0, 0,
254         1, 1, 0,
255         0, 1, 0
256 };
257
258 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
259 {
260         int i;
261         for (i = 0;i < verts;i++)
262         {
263                 out[0] = in[0] * r;
264                 out[1] = in[1] * g;
265                 out[2] = in[2] * b;
266                 out[3] = in[3];
267                 in += 4;
268                 out += 4;
269         }
270 }
271
272 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
273 {
274         int i;
275         for (i = 0;i < verts;i++)
276         {
277                 out[0] = r;
278                 out[1] = g;
279                 out[2] = b;
280                 out[3] = a;
281                 out += 4;
282         }
283 }
284
285 // FIXME: move this to client?
286 void FOG_clear(void)
287 {
288         if (gamemode == GAME_NEHAHRA)
289         {
290                 Cvar_Set("gl_fogenable", "0");
291                 Cvar_Set("gl_fogdensity", "0.2");
292                 Cvar_Set("gl_fogred", "0.3");
293                 Cvar_Set("gl_foggreen", "0.3");
294                 Cvar_Set("gl_fogblue", "0.3");
295         }
296         r_refdef.fog_density = 0;
297         r_refdef.fog_red = 0;
298         r_refdef.fog_green = 0;
299         r_refdef.fog_blue = 0;
300         r_refdef.fog_alpha = 1;
301         r_refdef.fog_start = 0;
302         r_refdef.fog_end = 16384;
303         r_refdef.fog_height = 1<<30;
304         r_refdef.fog_fadedepth = 128;
305 }
306
307 static void R_BuildBlankTextures(void)
308 {
309         unsigned char data[4];
310         data[2] = 128; // normal X
311         data[1] = 128; // normal Y
312         data[0] = 255; // normal Z
313         data[3] = 128; // height
314         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
315         data[0] = 255;
316         data[1] = 255;
317         data[2] = 255;
318         data[3] = 255;
319         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
320         data[0] = 128;
321         data[1] = 128;
322         data[2] = 128;
323         data[3] = 255;
324         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
325         data[0] = 0;
326         data[1] = 0;
327         data[2] = 0;
328         data[3] = 255;
329         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
330 }
331
332 static void R_BuildNoTexture(void)
333 {
334         int x, y;
335         unsigned char pix[16][16][4];
336         // this makes a light grey/dark grey checkerboard texture
337         for (y = 0;y < 16;y++)
338         {
339                 for (x = 0;x < 16;x++)
340                 {
341                         if ((y < 8) ^ (x < 8))
342                         {
343                                 pix[y][x][0] = 128;
344                                 pix[y][x][1] = 128;
345                                 pix[y][x][2] = 128;
346                                 pix[y][x][3] = 255;
347                         }
348                         else
349                         {
350                                 pix[y][x][0] = 64;
351                                 pix[y][x][1] = 64;
352                                 pix[y][x][2] = 64;
353                                 pix[y][x][3] = 255;
354                         }
355                 }
356         }
357         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
358 }
359
360 static void R_BuildWhiteCube(void)
361 {
362         unsigned char data[6*1*1*4];
363         memset(data, 255, sizeof(data));
364         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
365 }
366
367 static void R_BuildNormalizationCube(void)
368 {
369         int x, y, side;
370         vec3_t v;
371         vec_t s, t, intensity;
372 #define NORMSIZE 64
373         unsigned char *data;
374         data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
375         for (side = 0;side < 6;side++)
376         {
377                 for (y = 0;y < NORMSIZE;y++)
378                 {
379                         for (x = 0;x < NORMSIZE;x++)
380                         {
381                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
382                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
383                                 switch(side)
384                                 {
385                                 default:
386                                 case 0:
387                                         v[0] = 1;
388                                         v[1] = -t;
389                                         v[2] = -s;
390                                         break;
391                                 case 1:
392                                         v[0] = -1;
393                                         v[1] = -t;
394                                         v[2] = s;
395                                         break;
396                                 case 2:
397                                         v[0] = s;
398                                         v[1] = 1;
399                                         v[2] = t;
400                                         break;
401                                 case 3:
402                                         v[0] = s;
403                                         v[1] = -1;
404                                         v[2] = -t;
405                                         break;
406                                 case 4:
407                                         v[0] = s;
408                                         v[1] = -t;
409                                         v[2] = 1;
410                                         break;
411                                 case 5:
412                                         v[0] = -s;
413                                         v[1] = -t;
414                                         v[2] = -1;
415                                         break;
416                                 }
417                                 intensity = 127.0f / sqrt(DotProduct(v, v));
418                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
419                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
420                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
421                                 data[((side*64+y)*64+x)*4+3] = 255;
422                         }
423                 }
424         }
425         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
426         Mem_Free(data);
427 }
428
429 static void R_BuildFogTexture(void)
430 {
431         int x, b;
432 #define FOGWIDTH 256
433         unsigned char data1[FOGWIDTH][4];
434         //unsigned char data2[FOGWIDTH][4];
435         double d, r, alpha;
436
437         r_refdef.fogmasktable_start = r_refdef.fog_start;
438         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
439         r_refdef.fogmasktable_range = r_refdef.fogrange;
440         r_refdef.fogmasktable_density = r_refdef.fog_density;
441
442         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
443         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
444         {
445                 d = (x * r - r_refdef.fogmasktable_start);
446                 if(developer_extra.integer)
447                         Con_DPrintf("%f ", d);
448                 d = max(0, d);
449                 if (r_fog_exp2.integer)
450                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
451                 else
452                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
453                 if(developer_extra.integer)
454                         Con_DPrintf(" : %f ", alpha);
455                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
456                 if(developer_extra.integer)
457                         Con_DPrintf(" = %f\n", alpha);
458                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
459         }
460
461         for (x = 0;x < FOGWIDTH;x++)
462         {
463                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
464                 data1[x][0] = b;
465                 data1[x][1] = b;
466                 data1[x][2] = b;
467                 data1[x][3] = 255;
468                 //data2[x][0] = 255 - b;
469                 //data2[x][1] = 255 - b;
470                 //data2[x][2] = 255 - b;
471                 //data2[x][3] = 255;
472         }
473         if (r_texture_fogattenuation)
474         {
475                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
476                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
477         }
478         else
479         {
480                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, NULL);
481                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
482         }
483 }
484
485 //=======================================================================================================================================================
486
487 static const char *builtinshaderstring =
488 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
489 "// written by Forest 'LordHavoc' Hale\n"
490 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
491 "\n"
492 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
493 "# define USEFOG\n"
494 "#endif\n"
495 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
496 "#define USELIGHTMAP\n"
497 "#endif\n"
498 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
499 "#define USEEYEVECTOR\n"
500 "#endif\n"
501 "\n"
502 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
503 "# extension GL_ARB_texture_rectangle : enable\n"
504 "#endif\n"
505 "\n"
506 "#ifdef USESHADOWMAP2D\n"
507 "# ifdef GL_EXT_gpu_shader4\n"
508 "#   extension GL_EXT_gpu_shader4 : enable\n"
509 "# endif\n"
510 "# ifdef GL_ARB_texture_gather\n"
511 "#   extension GL_ARB_texture_gather : enable\n"
512 "# else\n"
513 "#   ifdef GL_AMD_texture_texture4\n"
514 "#     extension GL_AMD_texture_texture4 : enable\n"
515 "#   endif\n"
516 "# endif\n"
517 "#endif\n"
518 "\n"
519 "#ifdef USESHADOWMAPCUBE\n"
520 "# extension GL_EXT_gpu_shader4 : enable\n"
521 "#endif\n"
522 "\n"
523 "//#ifdef USESHADOWSAMPLER\n"
524 "//# extension GL_ARB_shadow : enable\n"
525 "//#endif\n"
526 "\n"
527 "//#ifdef __GLSL_CG_DATA_TYPES\n"
528 "//# define myhalf half\n"
529 "//# define myhalf2 half2\n"
530 "//# define myhalf3 half3\n"
531 "//# define myhalf4 half4\n"
532 "//#else\n"
533 "# define myhalf float\n"
534 "# define myhalf2 vec2\n"
535 "# define myhalf3 vec3\n"
536 "# define myhalf4 vec4\n"
537 "//#endif\n"
538 "\n"
539 "#ifdef VERTEX_SHADER\n"
540 "uniform mat4 ModelViewProjectionMatrix;\n"
541 "#endif\n"
542 "\n"
543 "#ifdef MODE_DEPTH_OR_SHADOW\n"
544 "#ifdef VERTEX_SHADER\n"
545 "void main(void)\n"
546 "{\n"
547 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
548 "}\n"
549 "#endif\n"
550 "#else // !MODE_DEPTH_ORSHADOW\n"
551 "\n"
552 "\n"
553 "\n"
554 "\n"
555 "#ifdef MODE_SHOWDEPTH\n"
556 "#ifdef VERTEX_SHADER\n"
557 "void main(void)\n"
558 "{\n"
559 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
560 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
561 "}\n"
562 "#endif\n"
563 "\n"
564 "#ifdef FRAGMENT_SHADER\n"
565 "void main(void)\n"
566 "{\n"
567 "       gl_FragColor = gl_Color;\n"
568 "}\n"
569 "#endif\n"
570 "#else // !MODE_SHOWDEPTH\n"
571 "\n"
572 "\n"
573 "\n"
574 "\n"
575 "#ifdef MODE_POSTPROCESS\n"
576 "varying vec2 TexCoord1;\n"
577 "varying vec2 TexCoord2;\n"
578 "\n"
579 "#ifdef VERTEX_SHADER\n"
580 "void main(void)\n"
581 "{\n"
582 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
583 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
584 "#ifdef USEBLOOM\n"
585 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
586 "#endif\n"
587 "}\n"
588 "#endif\n"
589 "\n"
590 "#ifdef FRAGMENT_SHADER\n"
591 "uniform sampler2D Texture_First;\n"
592 "#ifdef USEBLOOM\n"
593 "uniform sampler2D Texture_Second;\n"
594 "#endif\n"
595 "#ifdef USEGAMMARAMPS\n"
596 "uniform sampler2D Texture_GammaRamps;\n"
597 "#endif\n"
598 "#ifdef USESATURATION\n"
599 "uniform float Saturation;\n"
600 "#endif\n"
601 "#ifdef USEVIEWTINT\n"
602 "uniform vec4 ViewTintColor;\n"
603 "#endif\n"
604 "//uncomment these if you want to use them:\n"
605 "uniform vec4 UserVec1;\n"
606 "// uniform vec4 UserVec2;\n"
607 "// uniform vec4 UserVec3;\n"
608 "// uniform vec4 UserVec4;\n"
609 "// uniform float ClientTime;\n"
610 "uniform vec2 PixelSize;\n"
611 "void main(void)\n"
612 "{\n"
613 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
614 "#ifdef USEBLOOM\n"
615 "       gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
616 "#endif\n"
617 "#ifdef USEVIEWTINT\n"
618 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
619 "#endif\n"
620 "\n"
621 "#ifdef USEPOSTPROCESSING\n"
622 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
623 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
624 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
625 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
626 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
627 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
628 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
629 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
630 "#endif\n"
631 "\n"
632 "#ifdef USESATURATION\n"
633 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
634 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
635 "       //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
636 "       gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
637 "#endif\n"
638 "\n"
639 "#ifdef USEGAMMARAMPS\n"
640 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
641 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
642 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
643 "#endif\n"
644 "}\n"
645 "#endif\n"
646 "#else // !MODE_POSTPROCESS\n"
647 "\n"
648 "\n"
649 "\n"
650 "\n"
651 "#ifdef MODE_GENERIC\n"
652 "#ifdef USEDIFFUSE\n"
653 "varying vec2 TexCoord1;\n"
654 "#endif\n"
655 "#ifdef USESPECULAR\n"
656 "varying vec2 TexCoord2;\n"
657 "#endif\n"
658 "#ifdef VERTEX_SHADER\n"
659 "void main(void)\n"
660 "{\n"
661 "       gl_FrontColor = gl_Color;\n"
662 "#ifdef USEDIFFUSE\n"
663 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
664 "#endif\n"
665 "#ifdef USESPECULAR\n"
666 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
667 "#endif\n"
668 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
669 "}\n"
670 "#endif\n"
671 "\n"
672 "#ifdef FRAGMENT_SHADER\n"
673 "#ifdef USEDIFFUSE\n"
674 "uniform sampler2D Texture_First;\n"
675 "#endif\n"
676 "#ifdef USESPECULAR\n"
677 "uniform sampler2D Texture_Second;\n"
678 "#endif\n"
679 "\n"
680 "void main(void)\n"
681 "{\n"
682 "       gl_FragColor = gl_Color;\n"
683 "#ifdef USEDIFFUSE\n"
684 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
685 "#endif\n"
686 "\n"
687 "#ifdef USESPECULAR\n"
688 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
689 "# ifdef USECOLORMAPPING\n"
690 "       gl_FragColor *= tex2;\n"
691 "# endif\n"
692 "# ifdef USEGLOW\n"
693 "       gl_FragColor += tex2;\n"
694 "# endif\n"
695 "# ifdef USEVERTEXTEXTUREBLEND\n"
696 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
697 "# endif\n"
698 "#endif\n"
699 "}\n"
700 "#endif\n"
701 "#else // !MODE_GENERIC\n"
702 "\n"
703 "\n"
704 "\n"
705 "\n"
706 "#ifdef MODE_BLOOMBLUR\n"
707 "varying TexCoord;\n"
708 "#ifdef VERTEX_SHADER\n"
709 "void main(void)\n"
710 "{\n"
711 "       gl_FrontColor = gl_Color;\n"
712 "       TexCoord = gl_MultiTexCoord0.xy;\n"
713 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
714 "}\n"
715 "#endif\n"
716 "\n"
717 "#ifdef FRAGMENT_SHADER\n"
718 "uniform sampler2D Texture_First;\n"
719 "uniform vec4 BloomBlur_Parameters;\n"
720 "\n"
721 "void main(void)\n"
722 "{\n"
723 "       int i;\n"
724 "       vec2 tc = TexCoord;\n"
725 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
726 "       tc += BloomBlur_Parameters.xy;\n"
727 "       for (i = 1;i < SAMPLES;i++)\n"
728 "       {\n"
729 "               color += texture2D(Texture_First, tc).rgb;\n"
730 "               tc += BloomBlur_Parameters.xy;\n"
731 "       }\n"
732 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
733 "}\n"
734 "#endif\n"
735 "#else // !MODE_BLOOMBLUR\n"
736 "#ifdef MODE_REFRACTION\n"
737 "varying vec2 TexCoord;\n"
738 "varying vec4 ModelViewProjectionPosition;\n"
739 "uniform mat4 TexMatrix;\n"
740 "#ifdef VERTEX_SHADER\n"
741 "\n"
742 "void main(void)\n"
743 "{\n"
744 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
745 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
746 "       ModelViewProjectionPosition = gl_Position;\n"
747 "}\n"
748 "#endif\n"
749 "\n"
750 "#ifdef FRAGMENT_SHADER\n"
751 "uniform sampler2D Texture_Normal;\n"
752 "uniform sampler2D Texture_Refraction;\n"
753 "uniform sampler2D Texture_Reflection;\n"
754 "\n"
755 "uniform vec4 DistortScaleRefractReflect;\n"
756 "uniform vec4 ScreenScaleRefractReflect;\n"
757 "uniform vec4 ScreenCenterRefractReflect;\n"
758 "uniform vec4 RefractColor;\n"
759 "uniform vec4 ReflectColor;\n"
760 "uniform float ReflectFactor;\n"
761 "uniform float ReflectOffset;\n"
762 "\n"
763 "void main(void)\n"
764 "{\n"
765 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
766 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
767 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
768 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
769 "       // FIXME temporary hack to detect the case that the reflection\n"
770 "       // gets blackened at edges due to leaving the area that contains actual\n"
771 "       // content.\n"
772 "       // Remove this 'ack once we have a better way to stop this thing from\n"
773 "       // 'appening.\n"
774 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
775 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
776 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
777 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
778 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
779 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
780 "}\n"
781 "#endif\n"
782 "#else // !MODE_REFRACTION\n"
783 "\n"
784 "\n"
785 "\n"
786 "\n"
787 "#ifdef MODE_WATER\n"
788 "varying vec2 TexCoord;\n"
789 "varying vec3 EyeVector;\n"
790 "varying vec4 ModelViewProjectionPosition;\n"
791 "#ifdef VERTEX_SHADER\n"
792 "uniform vec3 EyePosition;\n"
793 "uniform mat4 TexMatrix;\n"
794 "\n"
795 "void main(void)\n"
796 "{\n"
797 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
798 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
799 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
800 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
801 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
802 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
803 "       ModelViewProjectionPosition = gl_Position;\n"
804 "}\n"
805 "#endif\n"
806 "\n"
807 "#ifdef FRAGMENT_SHADER\n"
808 "uniform sampler2D Texture_Normal;\n"
809 "uniform sampler2D Texture_Refraction;\n"
810 "uniform sampler2D Texture_Reflection;\n"
811 "\n"
812 "uniform vec4 DistortScaleRefractReflect;\n"
813 "uniform vec4 ScreenScaleRefractReflect;\n"
814 "uniform vec4 ScreenCenterRefractReflect;\n"
815 "uniform vec4 RefractColor;\n"
816 "uniform vec4 ReflectColor;\n"
817 "uniform float ReflectFactor;\n"
818 "uniform float ReflectOffset;\n"
819 "\n"
820 "void main(void)\n"
821 "{\n"
822 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
823 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
824 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
825 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
826 "       vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
827 "       // FIXME temporary hack to detect the case that the reflection\n"
828 "       // gets blackened at edges due to leaving the area that contains actual\n"
829 "       // content.\n"
830 "       // Remove this 'ack once we have a better way to stop this thing from\n"
831 "       // 'appening.\n"
832 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
833 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
834 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
835 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
836 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
837 "       f       = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
838 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
839 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
840 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
841 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
842 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
843 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
844 "}\n"
845 "#endif\n"
846 "#else // !MODE_WATER\n"
847 "\n"
848 "\n"
849 "\n"
850 "\n"
851 "// common definitions between vertex shader and fragment shader:\n"
852 "\n"
853 "varying vec2 TexCoord;\n"
854 "#ifdef USEVERTEXTEXTUREBLEND\n"
855 "varying vec2 TexCoord2;\n"
856 "#endif\n"
857 "#ifdef USELIGHTMAP\n"
858 "varying vec2 TexCoordLightmap;\n"
859 "#endif\n"
860 "\n"
861 "#ifdef MODE_LIGHTSOURCE\n"
862 "varying vec3 CubeVector;\n"
863 "#endif\n"
864 "\n"
865 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
866 "varying vec3 LightVector;\n"
867 "#endif\n"
868 "\n"
869 "#ifdef USEEYEVECTOR\n"
870 "varying vec3 EyeVector;\n"
871 "#endif\n"
872 "#ifdef USEFOG\n"
873 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
874 "#endif\n"
875 "\n"
876 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
877 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
878 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
879 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
880 "#endif\n"
881 "\n"
882 "#ifdef USEREFLECTION\n"
883 "varying vec4 ModelViewProjectionPosition;\n"
884 "#endif\n"
885 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
886 "uniform vec3 LightPosition;\n"
887 "varying vec4 ModelViewPosition;\n"
888 "#endif\n"
889 "\n"
890 "#ifdef MODE_LIGHTSOURCE\n"
891 "uniform vec3 LightPosition;\n"
892 "#endif\n"
893 "uniform vec3 EyePosition;\n"
894 "#ifdef MODE_LIGHTDIRECTION\n"
895 "uniform vec3 LightDir;\n"
896 "#endif\n"
897 "uniform vec4 FogPlane;\n"
898 "\n"
899 "#ifdef USESHADOWMAPORTHO\n"
900 "varying vec3 ShadowMapTC;\n"
901 "#endif\n"
902 "\n"
903 "\n"
904 "\n"
905 "\n"
906 "\n"
907 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
908 "\n"
909 "// fragment shader specific:\n"
910 "#ifdef FRAGMENT_SHADER\n"
911 "\n"
912 "uniform sampler2D Texture_Normal;\n"
913 "uniform sampler2D Texture_Color;\n"
914 "uniform sampler2D Texture_Gloss;\n"
915 "#ifdef USEGLOW\n"
916 "uniform sampler2D Texture_Glow;\n"
917 "#endif\n"
918 "#ifdef USEVERTEXTEXTUREBLEND\n"
919 "uniform sampler2D Texture_SecondaryNormal;\n"
920 "uniform sampler2D Texture_SecondaryColor;\n"
921 "uniform sampler2D Texture_SecondaryGloss;\n"
922 "#ifdef USEGLOW\n"
923 "uniform sampler2D Texture_SecondaryGlow;\n"
924 "#endif\n"
925 "#endif\n"
926 "#ifdef USECOLORMAPPING\n"
927 "uniform sampler2D Texture_Pants;\n"
928 "uniform sampler2D Texture_Shirt;\n"
929 "#endif\n"
930 "#ifdef USEFOG\n"
931 "uniform sampler2D Texture_FogMask;\n"
932 "#endif\n"
933 "#ifdef USELIGHTMAP\n"
934 "uniform sampler2D Texture_Lightmap;\n"
935 "#endif\n"
936 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
937 "uniform sampler2D Texture_Deluxemap;\n"
938 "#endif\n"
939 "#ifdef USEREFLECTION\n"
940 "uniform sampler2D Texture_Reflection;\n"
941 "#endif\n"
942 "\n"
943 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
944 "uniform sampler2D Texture_ScreenDepth;\n"
945 "uniform sampler2D Texture_ScreenNormalMap;\n"
946 "#endif\n"
947 "#ifdef USEDEFERREDLIGHTMAP\n"
948 "uniform sampler2D Texture_ScreenDiffuse;\n"
949 "uniform sampler2D Texture_ScreenSpecular;\n"
950 "#endif\n"
951 "\n"
952 "uniform myhalf3 Color_Pants;\n"
953 "uniform myhalf3 Color_Shirt;\n"
954 "uniform myhalf3 FogColor;\n"
955 "\n"
956 "#ifdef USEFOG\n"
957 "uniform float FogRangeRecip;\n"
958 "uniform float FogPlaneViewDist;\n"
959 "uniform float FogHeightFade;\n"
960 "float FogVertex(void)\n"
961 "{\n"
962 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
963 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
964 "       float fogfrac;\n"
965 "#ifdef USEFOGOUTSIDE\n"
966 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
967 "#else\n"
968 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
969 "#endif\n"
970 "       return float(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
971 "}\n"
972 "#endif\n"
973 "\n"
974 "#ifdef USEOFFSETMAPPING\n"
975 "uniform float OffsetMapping_Scale;\n"
976 "vec2 OffsetMapping(vec2 TexCoord)\n"
977 "{\n"
978 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
979 "       // 14 sample relief mapping: linear search and then binary search\n"
980 "       // this basically steps forward a small amount repeatedly until it finds\n"
981 "       // itself inside solid, then jitters forward and back using decreasing\n"
982 "       // amounts to find the impact\n"
983 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
984 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
985 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
986 "       vec3 RT = vec3(TexCoord, 1);\n"
987 "       OffsetVector *= 0.1;\n"
988 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
989 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
990 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
991 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
992 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
993 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
994 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
995 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
996 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
997 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
998 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
999 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1000 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1001 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1002 "       return RT.xy;\n"
1003 "#else\n"
1004 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1005 "       // this basically moves forward the full distance, and then backs up based\n"
1006 "       // on height of samples\n"
1007 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1008 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1009 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1010 "       TexCoord += OffsetVector;\n"
1011 "       OffsetVector *= 0.333;\n"
1012 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1013 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1014 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1015 "       return TexCoord;\n"
1016 "#endif\n"
1017 "}\n"
1018 "#endif // USEOFFSETMAPPING\n"
1019 "\n"
1020 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1021 "uniform sampler2D Texture_Attenuation;\n"
1022 "uniform samplerCube Texture_Cube;\n"
1023 "#endif\n"
1024 "\n"
1025 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1026 "\n"
1027 "#ifdef USESHADOWMAPRECT\n"
1028 "# ifdef USESHADOWSAMPLER\n"
1029 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1030 "# else\n"
1031 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1032 "# endif\n"
1033 "#endif\n"
1034 "\n"
1035 "#ifdef USESHADOWMAP2D\n"
1036 "# ifdef USESHADOWSAMPLER\n"
1037 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1038 "# else\n"
1039 "uniform sampler2D Texture_ShadowMap2D;\n"
1040 "# endif\n"
1041 "#endif\n"
1042 "\n"
1043 "#ifdef USESHADOWMAPVSDCT\n"
1044 "uniform samplerCube Texture_CubeProjection;\n"
1045 "#endif\n"
1046 "\n"
1047 "#ifdef USESHADOWMAPCUBE\n"
1048 "# ifdef USESHADOWSAMPLER\n"
1049 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1050 "# else\n"
1051 "uniform samplerCube Texture_ShadowMapCube;\n"
1052 "# endif\n"
1053 "#endif\n"
1054 "\n"
1055 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1056 "uniform vec2 ShadowMap_TextureScale;\n"
1057 "uniform vec4 ShadowMap_Parameters;\n"
1058 "#endif\n"
1059 "\n"
1060 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1061 "# ifdef USESHADOWMAPORTHO\n"
1062 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1063 "# else\n"
1064 "#  ifdef USESHADOWMAPVSDCT\n"
1065 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1066 "{\n"
1067 "       vec3 adir = abs(dir);\n"
1068 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1069 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1070 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1071 "}\n"
1072 "#  else\n"
1073 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1074 "{\n"
1075 "       vec3 adir = abs(dir);\n"
1076 "       float ma = adir.z;\n"
1077 "       vec4 proj = vec4(dir, 2.5);\n"
1078 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1079 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1080 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1081 "       return vec3(proj.xy * aparams.x + vec2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1082 "}\n"
1083 "#  endif\n"
1084 "# endif\n"
1085 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1086 "\n"
1087 "#ifdef USESHADOWMAPCUBE\n"
1088 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1089 "{\n"
1090 "       vec3 adir = abs(dir);\n"
1091 "       return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1092 "}\n"
1093 "#endif\n"
1094 "\n"
1095 "# ifdef USESHADOWMAPRECT\n"
1096 "float ShadowMapCompare(vec3 dir)\n"
1097 "{\n"
1098 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1099 "       float f;\n"
1100 "#  ifdef USESHADOWSAMPLER\n"
1101 "\n"
1102 "#    ifdef USESHADOWMAPPCF\n"
1103 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1104 "       f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1105 "#    else\n"
1106 "       f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1107 "#    endif\n"
1108 "\n"
1109 "#  else\n"
1110 "\n"
1111 "#    ifdef USESHADOWMAPPCF\n"
1112 "#      if USESHADOWMAPPCF > 1\n"
1113 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1114 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1115 "       vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1116 "       vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
1117 "       vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
1118 "       vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
1119 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1120 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1121 "#      else\n"
1122 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1123 "       vec2 offset = fract(shadowmaptc.xy);\n"
1124 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1125 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1126 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1127 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1128 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1129 "#      endif\n"
1130 "#    else\n"
1131 "       f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1132 "#    endif\n"
1133 "\n"
1134 "#  endif\n"
1135 "#  ifdef USESHADOWMAPORTHO\n"
1136 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1137 "#  else\n"
1138 "       return f;\n"
1139 "#  endif\n"
1140 "}\n"
1141 "# endif\n"
1142 "\n"
1143 "# ifdef USESHADOWMAP2D\n"
1144 "float ShadowMapCompare(vec3 dir)\n"
1145 "{\n"
1146 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1147 "       float f;\n"
1148 "\n"
1149 "#  ifdef USESHADOWSAMPLER\n"
1150 "#    ifdef USESHADOWMAPPCF\n"
1151 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1152 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1153 "       f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1154 "#    else\n"
1155 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1156 "#    endif\n"
1157 "#  else\n"
1158 "#    ifdef USESHADOWMAPPCF\n"
1159 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1160 "#      ifdef GL_ARB_texture_gather\n"
1161 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1162 "#      else\n"
1163 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1164 "#      endif\n"
1165 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1166 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1167 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1168 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1169 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1170 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1171 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1172 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1173 "#     else\n"
1174 "#      ifdef GL_EXT_gpu_shader4\n"
1175 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1176 "#      else\n"
1177 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1178 "#      endif\n"
1179 "#      if USESHADOWMAPPCF > 1\n"
1180 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1181 "       center *= ShadowMap_TextureScale;\n"
1182 "       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"
1183 "       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"
1184 "       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"
1185 "       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"
1186 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1187 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1188 "#      else\n"
1189 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1190 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1191 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1192 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1193 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1194 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1195 "#      endif\n"
1196 "#     endif\n"
1197 "#    else\n"
1198 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1199 "#    endif\n"
1200 "#  endif\n"
1201 "#  ifdef USESHADOWMAPORTHO\n"
1202 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1203 "#  else\n"
1204 "       return f;\n"
1205 "#  endif\n"
1206 "}\n"
1207 "# endif\n"
1208 "\n"
1209 "# ifdef USESHADOWMAPCUBE\n"
1210 "float ShadowMapCompare(vec3 dir)\n"
1211 "{\n"
1212 "       // apply depth texture cubemap as light filter\n"
1213 "       vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1214 "       float f;\n"
1215 "#  ifdef USESHADOWSAMPLER\n"
1216 "       f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1217 "#  else\n"
1218 "       f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1219 "#  endif\n"
1220 "       return f;\n"
1221 "}\n"
1222 "# endif\n"
1223 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1224 "#endif // FRAGMENT_SHADER\n"
1225 "\n"
1226 "\n"
1227 "\n"
1228 "\n"
1229 "#ifdef MODE_DEFERREDGEOMETRY\n"
1230 "#ifdef VERTEX_SHADER\n"
1231 "uniform mat4 TexMatrix;\n"
1232 "#ifdef USEVERTEXTEXTUREBLEND\n"
1233 "uniform mat4 BackgroundTexMatrix;\n"
1234 "#endif\n"
1235 "uniform mat4 ModelViewMatrix;\n"
1236 "void main(void)\n"
1237 "{\n"
1238 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1239 "#ifdef USEVERTEXTEXTUREBLEND\n"
1240 "       gl_FrontColor = gl_Color;\n"
1241 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1242 "#endif\n"
1243 "\n"
1244 "       // transform unnormalized eye direction into tangent space\n"
1245 "#ifdef USEOFFSETMAPPING\n"
1246 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1247 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1248 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1249 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1250 "#endif\n"
1251 "\n"
1252 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1253 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1254 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1255 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1256 "}\n"
1257 "#endif // VERTEX_SHADER\n"
1258 "\n"
1259 "#ifdef FRAGMENT_SHADER\n"
1260 "void main(void)\n"
1261 "{\n"
1262 "#ifdef USEOFFSETMAPPING\n"
1263 "       // apply offsetmapping\n"
1264 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1265 "#define TexCoord TexCoordOffset\n"
1266 "#endif\n"
1267 "\n"
1268 "#ifdef USEALPHAKILL\n"
1269 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1270 "               discard;\n"
1271 "#endif\n"
1272 "\n"
1273 "#ifdef USEVERTEXTEXTUREBLEND\n"
1274 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1275 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1276 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1277 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1278 "#endif\n"
1279 "\n"
1280 "#ifdef USEVERTEXTEXTUREBLEND\n"
1281 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1282 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1283 "#else\n"
1284 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1285 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1286 "#endif\n"
1287 "\n"
1288 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1289 "}\n"
1290 "#endif // FRAGMENT_SHADER\n"
1291 "#else // !MODE_DEFERREDGEOMETRY\n"
1292 "\n"
1293 "\n"
1294 "\n"
1295 "\n"
1296 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1297 "#ifdef VERTEX_SHADER\n"
1298 "uniform mat4 ModelViewMatrix;\n"
1299 "void main(void)\n"
1300 "{\n"
1301 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1302 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1303 "}\n"
1304 "#endif // VERTEX_SHADER\n"
1305 "\n"
1306 "#ifdef FRAGMENT_SHADER\n"
1307 "uniform mat4 ViewToLight;\n"
1308 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1309 "uniform vec2 ScreenToDepth;\n"
1310 "uniform myhalf3 DeferredColor_Ambient;\n"
1311 "uniform myhalf3 DeferredColor_Diffuse;\n"
1312 "#ifdef USESPECULAR\n"
1313 "uniform myhalf3 DeferredColor_Specular;\n"
1314 "uniform myhalf SpecularPower;\n"
1315 "#endif\n"
1316 "uniform myhalf2 PixelToScreenTexCoord;\n"
1317 "void main(void)\n"
1318 "{\n"
1319 "       // calculate viewspace pixel position\n"
1320 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1321 "       vec3 position;\n"
1322 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1323 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1324 "       // decode viewspace pixel normal\n"
1325 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1326 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1327 "       // surfacenormal = pixel normal in viewspace\n"
1328 "       // LightVector = pixel to light in viewspace\n"
1329 "       // CubeVector = position in lightspace\n"
1330 "       // eyevector = pixel to view in viewspace\n"
1331 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1332 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1333 "#ifdef USEDIFFUSE\n"
1334 "       // calculate diffuse shading\n"
1335 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1336 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1337 "#endif\n"
1338 "#ifdef USESPECULAR\n"
1339 "       // calculate directional shading\n"
1340 "       vec3 eyevector = position * -1.0;\n"
1341 "#  ifdef USEEXACTSPECULARMATH\n"
1342 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1343 "#  else\n"
1344 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1345 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1346 "#  endif\n"
1347 "#endif\n"
1348 "\n"
1349 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1350 "       fade *= ShadowMapCompare(CubeVector);\n"
1351 "#endif\n"
1352 "\n"
1353 "#ifdef USEDIFFUSE\n"
1354 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1355 "#else\n"
1356 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1357 "#endif\n"
1358 "#ifdef USESPECULAR\n"
1359 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1360 "#else\n"
1361 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1362 "#endif\n"
1363 "\n"
1364 "# ifdef USECUBEFILTER\n"
1365 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1366 "       gl_FragData[0].rgb *= cubecolor;\n"
1367 "       gl_FragData[1].rgb *= cubecolor;\n"
1368 "# endif\n"
1369 "}\n"
1370 "#endif // FRAGMENT_SHADER\n"
1371 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1372 "\n"
1373 "\n"
1374 "\n"
1375 "\n"
1376 "#ifdef VERTEX_SHADER\n"
1377 "uniform mat4 TexMatrix;\n"
1378 "#ifdef USEVERTEXTEXTUREBLEND\n"
1379 "uniform mat4 BackgroundTexMatrix;\n"
1380 "#endif\n"
1381 "#ifdef MODE_LIGHTSOURCE\n"
1382 "uniform mat4 ModelToLight;\n"
1383 "#endif\n"
1384 "#ifdef USESHADOWMAPORTHO\n"
1385 "uniform mat4 ShadowMapMatrix;\n"
1386 "#endif\n"
1387 "void main(void)\n"
1388 "{\n"
1389 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1390 "       gl_FrontColor = gl_Color;\n"
1391 "#endif\n"
1392 "       // copy the surface texcoord\n"
1393 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1394 "#ifdef USEVERTEXTEXTUREBLEND\n"
1395 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1396 "#endif\n"
1397 "#ifdef USELIGHTMAP\n"
1398 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1399 "#endif\n"
1400 "\n"
1401 "#ifdef MODE_LIGHTSOURCE\n"
1402 "       // transform vertex position into light attenuation/cubemap space\n"
1403 "       // (-1 to +1 across the light box)\n"
1404 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1405 "\n"
1406 "# ifdef USEDIFFUSE\n"
1407 "       // transform unnormalized light direction into tangent space\n"
1408 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1409 "       //  normalize it per pixel)\n"
1410 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1411 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1412 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1413 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1414 "# endif\n"
1415 "#endif\n"
1416 "\n"
1417 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1418 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1419 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1420 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1421 "#endif\n"
1422 "\n"
1423 "       // transform unnormalized eye direction into tangent space\n"
1424 "#ifdef USEEYEVECTOR\n"
1425 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1426 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1427 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1428 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1429 "#endif\n"
1430 "\n"
1431 "#ifdef USEFOG\n"
1432 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1433 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1434 "#endif\n"
1435 "\n"
1436 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1437 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1438 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1439 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1440 "#endif\n"
1441 "\n"
1442 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1443 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1444 "\n"
1445 "#ifdef USESHADOWMAPORTHO\n"
1446 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1447 "#endif\n"
1448 "\n"
1449 "#ifdef USEREFLECTION\n"
1450 "       ModelViewProjectionPosition = gl_Position;\n"
1451 "#endif\n"
1452 "}\n"
1453 "#endif // VERTEX_SHADER\n"
1454 "\n"
1455 "\n"
1456 "\n"
1457 "\n"
1458 "#ifdef FRAGMENT_SHADER\n"
1459 "#ifdef USEDEFERREDLIGHTMAP\n"
1460 "uniform myhalf2 PixelToScreenTexCoord;\n"
1461 "uniform myhalf3 DeferredMod_Diffuse;\n"
1462 "uniform myhalf3 DeferredMod_Specular;\n"
1463 "#endif\n"
1464 "uniform myhalf3 Color_Ambient;\n"
1465 "uniform myhalf3 Color_Diffuse;\n"
1466 "uniform myhalf3 Color_Specular;\n"
1467 "uniform myhalf SpecularPower;\n"
1468 "#ifdef USEGLOW\n"
1469 "uniform myhalf3 Color_Glow;\n"
1470 "#endif\n"
1471 "uniform myhalf Alpha;\n"
1472 "#ifdef USEREFLECTION\n"
1473 "uniform vec4 DistortScaleRefractReflect;\n"
1474 "uniform vec4 ScreenScaleRefractReflect;\n"
1475 "uniform vec4 ScreenCenterRefractReflect;\n"
1476 "uniform myhalf4 ReflectColor;\n"
1477 "#endif\n"
1478 "#ifdef USEREFLECTCUBE\n"
1479 "uniform mat4 ModelToReflectCube;\n"
1480 "uniform sampler2D Texture_ReflectMask;\n"
1481 "uniform samplerCube Texture_ReflectCube;\n"
1482 "#endif\n"
1483 "#ifdef MODE_LIGHTDIRECTION\n"
1484 "uniform myhalf3 LightColor;\n"
1485 "#endif\n"
1486 "#ifdef MODE_LIGHTSOURCE\n"
1487 "uniform myhalf3 LightColor;\n"
1488 "#endif\n"
1489 "void main(void)\n"
1490 "{\n"
1491 "#ifdef USEOFFSETMAPPING\n"
1492 "       // apply offsetmapping\n"
1493 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1494 "#define TexCoord TexCoordOffset\n"
1495 "#endif\n"
1496 "\n"
1497 "       // combine the diffuse textures (base, pants, shirt)\n"
1498 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1499 "#ifdef USEALPHAKILL\n"
1500 "       if (color.a < 0.5)\n"
1501 "               discard;\n"
1502 "#endif\n"
1503 "       color.a *= Alpha;\n"
1504 "#ifdef USECOLORMAPPING\n"
1505 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1506 "#endif\n"
1507 "#ifdef USEVERTEXTEXTUREBLEND\n"
1508 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1509 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1510 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1511 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1512 "       color.a = 1.0;\n"
1513 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1514 "#endif\n"
1515 "\n"
1516 "       // get the surface normal\n"
1517 "#ifdef USEVERTEXTEXTUREBLEND\n"
1518 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1519 "#else\n"
1520 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1521 "#endif\n"
1522 "\n"
1523 "       // get the material colors\n"
1524 "       myhalf3 diffusetex = color.rgb;\n"
1525 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1526 "# ifdef USEVERTEXTEXTUREBLEND\n"
1527 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1528 "# else\n"
1529 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1530 "# endif\n"
1531 "#endif\n"
1532 "\n"
1533 "#ifdef USEREFLECTCUBE\n"
1534 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1535 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1536 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1537 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1538 "#endif\n"
1539 "\n"
1540 "\n"
1541 "\n"
1542 "\n"
1543 "#ifdef MODE_LIGHTSOURCE\n"
1544 "       // light source\n"
1545 "#ifdef USEDIFFUSE\n"
1546 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1547 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1548 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1549 "#ifdef USESPECULAR\n"
1550 "#ifdef USEEXACTSPECULARMATH\n"
1551 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1552 "#else\n"
1553 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1554 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1555 "#endif\n"
1556 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1557 "#endif\n"
1558 "#else\n"
1559 "       color.rgb = diffusetex * Color_Ambient;\n"
1560 "#endif\n"
1561 "       color.rgb *= LightColor;\n"
1562 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1563 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1564 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1565 "#endif\n"
1566 "# ifdef USECUBEFILTER\n"
1567 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1568 "# endif\n"
1569 "#endif // MODE_LIGHTSOURCE\n"
1570 "\n"
1571 "\n"
1572 "\n"
1573 "\n"
1574 "#ifdef MODE_LIGHTDIRECTION\n"
1575 "#define SHADING\n"
1576 "#ifdef USEDIFFUSE\n"
1577 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1578 "#endif\n"
1579 "#define lightcolor LightColor\n"
1580 "#endif // MODE_LIGHTDIRECTION\n"
1581 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1582 "#define SHADING\n"
1583 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1584 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1585 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1586 "       // convert modelspace light vector to tangentspace\n"
1587 "       myhalf3 lightnormal;\n"
1588 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1589 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1590 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1591 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1592 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1593 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1594 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1595 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1596 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1597 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1598 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1599 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1600 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1601 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1602 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1603 "#define SHADING\n"
1604 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1605 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1606 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1607 "#endif\n"
1608 "\n"
1609 "\n"
1610 "\n"
1611 "\n"
1612 "#ifdef MODE_LIGHTMAP\n"
1613 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1614 "#endif // MODE_LIGHTMAP\n"
1615 "#ifdef MODE_VERTEXCOLOR\n"
1616 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1617 "#endif // MODE_VERTEXCOLOR\n"
1618 "#ifdef MODE_FLATCOLOR\n"
1619 "       color.rgb = diffusetex * Color_Ambient;\n"
1620 "#endif // MODE_FLATCOLOR\n"
1621 "\n"
1622 "\n"
1623 "\n"
1624 "\n"
1625 "#ifdef SHADING\n"
1626 "# ifdef USEDIFFUSE\n"
1627 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1628 "#  ifdef USESPECULAR\n"
1629 "#   ifdef USEEXACTSPECULARMATH\n"
1630 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1631 "#   else\n"
1632 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1633 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1634 "#   endif\n"
1635 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1636 "#  else\n"
1637 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1638 "#  endif\n"
1639 "# else\n"
1640 "       color.rgb = diffusetex * Color_Ambient;\n"
1641 "# endif\n"
1642 "#endif\n"
1643 "\n"
1644 "#ifdef USESHADOWMAPORTHO\n"
1645 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1646 "#endif\n"
1647 "\n"
1648 "#ifdef USEDEFERREDLIGHTMAP\n"
1649 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1650 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1651 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1652 "#endif\n"
1653 "\n"
1654 "#ifdef USEGLOW\n"
1655 "#ifdef USEVERTEXTEXTUREBLEND\n"
1656 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1657 "#else\n"
1658 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1659 "#endif\n"
1660 "#endif\n"
1661 "\n"
1662 "#ifdef USEFOG\n"
1663 "#ifdef MODE_LIGHTSOURCE\n"
1664 "       color.rgb *= myhalf(FogVertex());\n"
1665 "#else\n"
1666 "       color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1667 "#endif\n"
1668 "#endif\n"
1669 "\n"
1670 "       // 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"
1671 "#ifdef USEREFLECTION\n"
1672 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1673 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1674 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1675 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1676 "       // FIXME temporary hack to detect the case that the reflection\n"
1677 "       // gets blackened at edges due to leaving the area that contains actual\n"
1678 "       // content.\n"
1679 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1680 "       // 'appening.\n"
1681 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1682 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1683 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1684 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1685 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1686 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1687 "#endif\n"
1688 "\n"
1689 "       gl_FragColor = vec4(color);\n"
1690 "}\n"
1691 "#endif // FRAGMENT_SHADER\n"
1692 "\n"
1693 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1694 "#endif // !MODE_DEFERREDGEOMETRY\n"
1695 "#endif // !MODE_WATER\n"
1696 "#endif // !MODE_REFRACTION\n"
1697 "#endif // !MODE_BLOOMBLUR\n"
1698 "#endif // !MODE_GENERIC\n"
1699 "#endif // !MODE_POSTPROCESS\n"
1700 "#endif // !MODE_SHOWDEPTH\n"
1701 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1702 ;
1703
1704 /*
1705 =========================================================================================================================================================
1706
1707
1708
1709 =========================================================================================================================================================
1710
1711
1712
1713 =========================================================================================================================================================
1714
1715
1716
1717 =========================================================================================================================================================
1718
1719
1720
1721 =========================================================================================================================================================
1722
1723
1724
1725 =========================================================================================================================================================
1726
1727
1728
1729 =========================================================================================================================================================
1730 */
1731
1732 const char *builtincgshaderstring =
1733 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1734 "// written by Forest 'LordHavoc' Hale\n"
1735 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1736 "\n"
1737 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
1738 "# define USEFOG\n"
1739 "#endif\n"
1740 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1741 "#define USELIGHTMAP\n"
1742 "#endif\n"
1743 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
1744 "#define USEEYEVECTOR\n"
1745 "#endif\n"
1746 "\n"
1747 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1748 "#ifdef VERTEX_SHADER\n"
1749 "void main\n"
1750 "(\n"
1751 "float4 gl_Vertex : POSITION,\n"
1752 "uniform float4x4 ModelViewProjectionMatrix,\n"
1753 "out float4 gl_Position : POSITION\n"
1754 ")\n"
1755 "{\n"
1756 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1757 "}\n"
1758 "#endif\n"
1759 "#else // !MODE_DEPTH_ORSHADOW\n"
1760 "\n"
1761 "\n"
1762 "\n"
1763 "\n"
1764 "#ifdef MODE_SHOWDEPTH\n"
1765 "#ifdef VERTEX_SHADER\n"
1766 "void main\n"
1767 "(\n"
1768 "float4 gl_Vertex : POSITION,\n"
1769 "uniform float4x4 ModelViewProjectionMatrix,\n"
1770 "out float4 gl_Position : POSITION,\n"
1771 "out float4 gl_FrontColor : COLOR0\n"
1772 ")\n"
1773 "{\n"
1774 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1775 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1776 "}\n"
1777 "#endif\n"
1778 "\n"
1779 "#ifdef FRAGMENT_SHADER\n"
1780 "void main\n"
1781 "(\n"
1782 "float4 gl_FrontColor : COLOR0,\n"
1783 "out float4 gl_FragColor : COLOR\n"
1784 ")\n"
1785 "{\n"
1786 "       gl_FragColor = gl_FrontColor;\n"
1787 "}\n"
1788 "#endif\n"
1789 "#else // !MODE_SHOWDEPTH\n"
1790 "\n"
1791 "\n"
1792 "\n"
1793 "\n"
1794 "#ifdef MODE_POSTPROCESS\n"
1795 "\n"
1796 "#ifdef VERTEX_SHADER\n"
1797 "void main\n"
1798 "(\n"
1799 "float4 gl_Vertex : POSITION,\n"
1800 "uniform float4x4 ModelViewProjectionMatrix,\n"
1801 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1802 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1803 "out float4 gl_Position : POSITION,\n"
1804 "out float2 TexCoord1 : TEXCOORD0,\n"
1805 "out float2 TexCoord2 : TEXCOORD1\n"
1806 ")\n"
1807 "{\n"
1808 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1809 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1810 "#ifdef USEBLOOM\n"
1811 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1812 "#endif\n"
1813 "}\n"
1814 "#endif\n"
1815 "\n"
1816 "#ifdef FRAGMENT_SHADER\n"
1817 "void main\n"
1818 "(\n"
1819 "float2 TexCoord1 : TEXCOORD0,\n"
1820 "float2 TexCoord2 : TEXCOORD1,\n"
1821 "uniform sampler2D Texture_First,\n"
1822 "#ifdef USEBLOOM\n"
1823 "uniform sampler2D Texture_Second,\n"
1824 "#endif\n"
1825 "#ifdef USEGAMMARAMPS\n"
1826 "uniform sampler2D Texture_GammaRamps,\n"
1827 "#endif\n"
1828 "#ifdef USESATURATION\n"
1829 "uniform float Saturation,\n"
1830 "#endif\n"
1831 "#ifdef USEVIEWTINT\n"
1832 "uniform float4 ViewTintColor,\n"
1833 "#endif\n"
1834 "uniform float4 UserVec1,\n"
1835 "uniform float4 UserVec2,\n"
1836 "uniform float4 UserVec3,\n"
1837 "uniform float4 UserVec4,\n"
1838 "uniform float ClientTime,\n"
1839 "uniform float2 PixelSize,\n"
1840 "out float4 gl_FragColor : COLOR\n"
1841 ")\n"
1842 "{\n"
1843 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1844 "#ifdef USEBLOOM\n"
1845 "       gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
1846 "#endif\n"
1847 "#ifdef USEVIEWTINT\n"
1848 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1849 "#endif\n"
1850 "\n"
1851 "#ifdef USEPOSTPROCESSING\n"
1852 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1853 "// 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"
1854 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1855 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1856 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1857 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
1858 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
1859 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
1860 "#endif\n"
1861 "\n"
1862 "#ifdef USESATURATION\n"
1863 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
1864 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
1865 "       //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
1866 "       gl_FragColor.rgb = lerp(float3(y), gl_FragColor.rgb, Saturation);\n"
1867 "#endif\n"
1868 "\n"
1869 "#ifdef USEGAMMARAMPS\n"
1870 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
1871 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
1872 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
1873 "#endif\n"
1874 "}\n"
1875 "#endif\n"
1876 "#else // !MODE_POSTPROCESS\n"
1877 "\n"
1878 "\n"
1879 "\n"
1880 "\n"
1881 "#ifdef MODE_GENERIC\n"
1882 "#ifdef VERTEX_SHADER\n"
1883 "void main\n"
1884 "(\n"
1885 "float4 gl_Vertex : POSITION,\n"
1886 "uniform float4x4 ModelViewProjectionMatrix,\n"
1887 "float4 gl_Color : COLOR0,\n"
1888 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1889 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1890 "out float4 gl_Position : POSITION,\n"
1891 "out float4 gl_FrontColor : COLOR,\n"
1892 "out float2 TexCoord1 : TEXCOORD0,\n"
1893 "out float2 TexCoord2 : TEXCOORD1\n"
1894 ")\n"
1895 "{\n"
1896 "       gl_FrontColor = gl_Color;\n"
1897 "#ifdef USEDIFFUSE\n"
1898 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1899 "#endif\n"
1900 "#ifdef USESPECULAR\n"
1901 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1902 "#endif\n"
1903 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1904 "}\n"
1905 "#endif\n"
1906 "\n"
1907 "#ifdef FRAGMENT_SHADER\n"
1908 "\n"
1909 "void main\n"
1910 "(\n"
1911 "float4 gl_FrontColor : COLOR,\n"
1912 "float2 TexCoord1 : TEXCOORD0,\n"
1913 "float2 TexCoord2 : TEXCOORD1,\n"
1914 "#ifdef USEDIFFUSE\n"
1915 "uniform sampler2D Texture_First,\n"
1916 "#endif\n"
1917 "#ifdef USESPECULAR\n"
1918 "uniform sampler2D Texture_Second,\n"
1919 "#endif\n"
1920 "out float4 gl_FragColor : COLOR\n"
1921 ")\n"
1922 "{\n"
1923 "       gl_FragColor = gl_FrontColor;\n"
1924 "#ifdef USEDIFFUSE\n"
1925 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
1926 "#endif\n"
1927 "\n"
1928 "#ifdef USESPECULAR\n"
1929 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
1930 "# ifdef USECOLORMAPPING\n"
1931 "       gl_FragColor *= tex2;\n"
1932 "# endif\n"
1933 "# ifdef USEGLOW\n"
1934 "       gl_FragColor += tex2;\n"
1935 "# endif\n"
1936 "# ifdef USEVERTEXTEXTUREBLEND\n"
1937 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
1938 "# endif\n"
1939 "#endif\n"
1940 "}\n"
1941 "#endif\n"
1942 "#else // !MODE_GENERIC\n"
1943 "\n"
1944 "\n"
1945 "\n"
1946 "\n"
1947 "#ifdef MODE_BLOOMBLUR\n"
1948 "#ifdef VERTEX_SHADER\n"
1949 "void main\n"
1950 "(\n"
1951 "float4 gl_Vertex : POSITION,\n"
1952 "uniform float4x4 ModelViewProjectionMatrix,\n"
1953 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1954 "out float4 gl_Position : POSITION,\n"
1955 "out float2 TexCoord : TEXCOORD0\n"
1956 ")\n"
1957 "{\n"
1958 "       TexCoord = gl_MultiTexCoord0.xy;\n"
1959 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1960 "}\n"
1961 "#endif\n"
1962 "\n"
1963 "#ifdef FRAGMENT_SHADER\n"
1964 "\n"
1965 "void main\n"
1966 "(\n"
1967 "float2 TexCoord : TEXCOORD0,\n"
1968 "uniform sampler2D Texture_First,\n"
1969 "uniform float4 BloomBlur_Parameters,\n"
1970 "out float4 gl_FragColor : COLOR\n"
1971 ")\n"
1972 "{\n"
1973 "       int i;\n"
1974 "       float2 tc = TexCoord;\n"
1975 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
1976 "       tc += BloomBlur_Parameters.xy;\n"
1977 "       for (i = 1;i < SAMPLES;i++)\n"
1978 "       {\n"
1979 "               color += tex2D(Texture_First, tc).rgb;\n"
1980 "               tc += BloomBlur_Parameters.xy;\n"
1981 "       }\n"
1982 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
1983 "}\n"
1984 "#endif\n"
1985 "#else // !MODE_BLOOMBLUR\n"
1986 "#ifdef MODE_REFRACTION\n"
1987 "#ifdef VERTEX_SHADER\n"
1988 "void main\n"
1989 "(\n"
1990 "float4 gl_Vertex : POSITION,\n"
1991 "uniform float4x4 ModelViewProjectionMatrix,\n"
1992 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1993 "uniform float4x4 TexMatrix,\n"
1994 "uniform float3 EyePosition,\n"
1995 "out float4 gl_Position : POSITION,\n"
1996 "out float2 TexCoord : TEXCOORD0,\n"
1997 "out float3 EyeVector : TEXCOORD1,\n"
1998 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
1999 ")\n"
2000 "{\n"
2001 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2002 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2003 "       ModelViewProjectionPosition = gl_Position;\n"
2004 "}\n"
2005 "#endif\n"
2006 "\n"
2007 "#ifdef FRAGMENT_SHADER\n"
2008 "void main\n"
2009 "(\n"
2010 "float2 TexCoord : TEXCOORD0,\n"
2011 "float3 EyeVector : TEXCOORD1,\n"
2012 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2013 "uniform sampler2D Texture_Normal,\n"
2014 "uniform sampler2D Texture_Refraction,\n"
2015 "uniform sampler2D Texture_Reflection,\n"
2016 "uniform float4 DistortScaleRefractReflect,\n"
2017 "uniform float4 ScreenScaleRefractReflect,\n"
2018 "uniform float4 ScreenCenterRefractReflect,\n"
2019 "uniform float4 RefractColor,\n"
2020 "out float4 gl_FragColor : COLOR\n"
2021 ")\n"
2022 "{\n"
2023 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2024 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2025 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2026 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
2027 "       // FIXME temporary hack to detect the case that the reflection\n"
2028 "       // gets blackened at edges due to leaving the area that contains actual\n"
2029 "       // content.\n"
2030 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2031 "       // 'appening.\n"
2032 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2033 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2034 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2035 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2036 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2037 "       gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2038 "}\n"
2039 "#endif\n"
2040 "#else // !MODE_REFRACTION\n"
2041 "\n"
2042 "\n"
2043 "\n"
2044 "\n"
2045 "#ifdef MODE_WATER\n"
2046 "#ifdef VERTEX_SHADER\n"
2047 "\n"
2048 "void main\n"
2049 "(\n"
2050 "float4 gl_Vertex : POSITION,\n"
2051 "uniform float4x4 ModelViewProjectionMatrix,\n"
2052 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2053 "uniform float4x4 TexMatrix,\n"
2054 "uniform float3 EyePosition,\n"
2055 "out float4 gl_Position : POSITION,\n"
2056 "out float2 TexCoord : TEXCOORD0,\n"
2057 "out float3 EyeVector : TEXCOORD1,\n"
2058 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2059 ")\n"
2060 "{\n"
2061 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2062 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2063 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2064 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2065 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2066 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2067 "       ModelViewProjectionPosition = gl_Position;\n"
2068 "}\n"
2069 "#endif\n"
2070 "\n"
2071 "#ifdef FRAGMENT_SHADER\n"
2072 "void main\n"
2073 "(\n"
2074 "float2 TexCoord : TEXCOORD0,\n"
2075 "float3 EyeVector : TEXCOORD1,\n"
2076 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2077 "uniform sampler2D Texture_Normal,\n"
2078 "uniform sampler2D Texture_Refraction,\n"
2079 "uniform sampler2D Texture_Reflection,\n"
2080 "uniform float4 DistortScaleRefractReflect,\n"
2081 "uniform float4 ScreenScaleRefractReflect,\n"
2082 "uniform float4 ScreenCenterRefractReflect,\n"
2083 "uniform float4 RefractColor,\n"
2084 "uniform float4 ReflectColor,\n"
2085 "uniform float ReflectFactor,\n"
2086 "uniform float ReflectOffset,\n"
2087 "out float4 gl_FragColor : COLOR\n"
2088 ")\n"
2089 "{\n"
2090 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2091 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2092 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2093 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xyxy * DistortScaleRefractReflect;\n"
2094 "       // FIXME temporary hack to detect the case that the reflection\n"
2095 "       // gets blackened at edges due to leaving the area that contains actual\n"
2096 "       // content.\n"
2097 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2098 "       // 'appening.\n"
2099 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2100 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2101 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2102 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2103 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2104 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2105 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2106 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2107 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2108 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2109 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2110 "       gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2111 "}\n"
2112 "#endif\n"
2113 "#else // !MODE_WATER\n"
2114 "\n"
2115 "\n"
2116 "\n"
2117 "\n"
2118 "// 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"
2119 "\n"
2120 "// fragment shader specific:\n"
2121 "#ifdef FRAGMENT_SHADER\n"
2122 "\n"
2123 "#ifdef USEFOG\n"
2124 "float FogVertex(float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask)\n"
2125 "{\n"
2126 "       float fogfrac;\n"
2127 "#ifdef USEFOGOUTSIDE\n"
2128 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2129 "#else\n"
2130 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2131 "#endif\n"
2132 "       return float(tex2D(Texture_FogMask, half2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
2133 "}\n"
2134 "#endif\n"
2135 "\n"
2136 "#ifdef USEOFFSETMAPPING\n"
2137 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler2D Texture_Normal)\n"
2138 "{\n"
2139 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2140 "       // 14 sample relief mapping: linear search and then binary search\n"
2141 "       // this basically steps forward a small amount repeatedly until it finds\n"
2142 "       // itself inside solid, then jitters forward and back using decreasing\n"
2143 "       // amounts to find the impact\n"
2144 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2145 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2146 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2147 "       float3 RT = float3(TexCoord, 1);\n"
2148 "       OffsetVector *= 0.1;\n"
2149 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2150 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2151 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2152 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2153 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2154 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2155 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2156 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2157 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2158 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2159 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2160 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2161 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2162 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2163 "       return RT.xy;\n"
2164 "#else\n"
2165 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2166 "       // this basically moves forward the full distance, and then backs up based\n"
2167 "       // on height of samples\n"
2168 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2169 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2170 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2171 "       TexCoord += OffsetVector;\n"
2172 "       OffsetVector *= 0.333;\n"
2173 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2174 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2175 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2176 "       return TexCoord;\n"
2177 "#endif\n"
2178 "}\n"
2179 "#endif // USEOFFSETMAPPING\n"
2180 "\n"
2181 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2182 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2183 "# ifdef USESHADOWMAPORTHO\n"
2184 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2185 "# else\n"
2186 "#  ifdef USESHADOWMAPVSDCT\n"
2187 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2188 "{\n"
2189 "       float3 adir = abs(dir);\n"
2190 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2191 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2192 "       return float3(lerp(dir.xy, proj.xy, dir.zz) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2193 "}\n"
2194 "#  else\n"
2195 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2196 "{\n"
2197 "       float3 adir = abs(dir);\n"
2198 "       float ma = adir.z;\n"
2199 "       float4 proj = float4(dir, 2.5);\n"
2200 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2201 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2202 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2203 "       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"
2204 "}\n"
2205 "#  endif\n"
2206 "# endif\n"
2207 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPORTHO)\n"
2208 "\n"
2209 "#ifdef USESHADOWMAPCUBE\n"
2210 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2211 "{\n"
2212 "    float3 adir = abs(dir);\n"
2213 "    return float4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
2214 "}\n"
2215 "#endif\n"
2216 "\n"
2217 "# ifdef USESHADOWMAPRECT\n"
2218 "#ifdef USESHADOWMAPVSDCT\n"
2219 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2220 "#else\n"
2221 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2222 "#endif\n"
2223 "{\n"
2224 "#ifdef USESHADOWMAPVSDCT\n"
2225 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2226 "#else\n"
2227 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2228 "#endif\n"
2229 "       float f;\n"
2230 "#  ifdef USESHADOWSAMPLER\n"
2231 "\n"
2232 "#    ifdef USESHADOWMAPPCF\n"
2233 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2234 "    f = dot(float4(0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2235 "#    else\n"
2236 "    f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2237 "#    endif\n"
2238 "\n"
2239 "#  else\n"
2240 "\n"
2241 "#    ifdef USESHADOWMAPPCF\n"
2242 "#      if USESHADOWMAPPCF > 1\n"
2243 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2244 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2245 "    float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
2246 "    float4 row2 = step(shadowmaptc.z, float4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
2247 "    float4 row3 = step(shadowmaptc.z, float4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
2248 "    float4 row4 = step(shadowmaptc.z, float4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
2249 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2250 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2251 "#      else\n"
2252 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2253 "    float2 offset = frac(shadowmaptc.xy);\n"
2254 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2255 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2256 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2257 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2258 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2259 "#      endif\n"
2260 "#    else\n"
2261 "    f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2262 "#    endif\n"
2263 "\n"
2264 "#  endif\n"
2265 "#  ifdef USESHADOWMAPORTHO\n"
2266 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2267 "#  else\n"
2268 "       return f;\n"
2269 "#  endif\n"
2270 "}\n"
2271 "# endif\n"
2272 "\n"
2273 "# ifdef USESHADOWMAP2D\n"
2274 "#ifdef USESHADOWMAPVSDCT\n"
2275 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2276 "#else\n"
2277 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2278 "#endif\n"
2279 "{\n"
2280 "#ifdef USESHADOWMAPVSDCT\n"
2281 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2282 "#else\n"
2283 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2284 "#endif\n"
2285 "    float f;\n"
2286 "\n"
2287 "#  ifdef USESHADOWSAMPLER\n"
2288 "#    ifdef USESHADOWMAPPCF\n"
2289 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, float3(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
2290 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2291 "    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"
2292 "#    else\n"
2293 "    f = shadow2D(Texture_ShadowMap2D, float3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
2294 "#    endif\n"
2295 "#  else\n"
2296 "#    ifdef USESHADOWMAPPCF\n"
2297 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2298 "#      ifdef GL_ARB_texture_gather\n"
2299 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
2300 "#      else\n"
2301 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2302 "#      endif\n"
2303 "    float2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2304 "    float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2305 "    float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2306 "    float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2307 "    float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2308 "    float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2309 "                lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2310 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2311 "#     else\n"
2312 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)  \n"
2313 "#      if USESHADOWMAPPCF > 1\n"
2314 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2315 "    center *= ShadowMap_TextureScale;\n"
2316 "    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"
2317 "    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"
2318 "    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"
2319 "    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"
2320 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2321 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2322 "#      else\n"
2323 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2324 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2325 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2326 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2327 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2328 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2329 "#      endif\n"
2330 "#     endif\n"
2331 "#    else\n"
2332 "    f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2333 "#    endif\n"
2334 "#  endif\n"
2335 "#  ifdef USESHADOWMAPORTHO\n"
2336 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2337 "#  else\n"
2338 "       return f;\n"
2339 "#  endif\n"
2340 "}\n"
2341 "# endif\n"
2342 "\n"
2343 "# ifdef USESHADOWMAPCUBE\n"
2344 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2345 "{\n"
2346 "    // apply depth texture cubemap as light filter\n"
2347 "    float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2348 "    float f;\n"
2349 "#  ifdef USESHADOWSAMPLER\n"
2350 "    f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2351 "#  else\n"
2352 "    f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2353 "#  endif\n"
2354 "    return f;\n"
2355 "}\n"
2356 "# endif\n"
2357 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2358 "#endif // FRAGMENT_SHADER\n"
2359 "\n"
2360 "\n"
2361 "\n"
2362 "\n"
2363 "#ifdef MODE_DEFERREDGEOMETRY\n"
2364 "#ifdef VERTEX_SHADER\n"
2365 "void main\n"
2366 "(\n"
2367 "float4 gl_Vertex : POSITION,\n"
2368 "uniform float4x4 ModelViewProjectionMatrix,\n"
2369 "#ifdef USEVERTEXTEXTUREBLEND\n"
2370 "float4 gl_Color : COLOR0,\n"
2371 "#endif\n"
2372 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2373 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2374 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2375 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2376 "uniform float4x4 TexMatrix,\n"
2377 "#ifdef USEVERTEXTEXTUREBLEND\n"
2378 "uniform float4x4 BackgroundTexMatrix,\n"
2379 "#endif\n"
2380 "uniform float4x4 ModelViewMatrix,\n"
2381 "#ifdef USEOFFSETMAPPING\n"
2382 "uniform float3 EyePosition,\n"
2383 "#endif\n"
2384 "out float4 gl_Position : POSITION,\n"
2385 "out float4 gl_FrontColor : COLOR,\n"
2386 "out float4 TexCoordBoth : TEXCOORD0,\n"
2387 "#ifdef USEOFFSETMAPPING\n"
2388 "out float3 EyeVector : TEXCOORD2,\n"
2389 "#endif\n"
2390 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2391 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2392 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2393 ")\n"
2394 "{\n"
2395 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2396 "#ifdef USEVERTEXTEXTUREBLEND\n"
2397 "       gl_FrontColor = gl_Color;\n"
2398 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2399 "#endif\n"
2400 "\n"
2401 "       // transform unnormalized eye direction into tangent space\n"
2402 "#ifdef USEOFFSETMAPPING\n"
2403 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2404 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2405 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2406 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2407 "#endif\n"
2408 "\n"
2409 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2410 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2411 "       VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2412 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2413 "}\n"
2414 "#endif // VERTEX_SHADER\n"
2415 "\n"
2416 "#ifdef FRAGMENT_SHADER\n"
2417 "void main\n"
2418 "(\n"
2419 "float4 TexCoordBoth : TEXCOORD0,\n"
2420 "float3 EyeVector : TEXCOORD2,\n"
2421 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2422 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2423 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2424 "uniform sampler2D Texture_Normal,\n"
2425 "#ifdef USEALPHAKILL\n"
2426 "uniform sampler2D Texture_Color,\n"
2427 "#endif\n"
2428 "uniform sampler2D Texture_Gloss,\n"
2429 "#ifdef USEVERTEXTEXTUREBLEND\n"
2430 "uniform sampler2D Texture_SecondaryNormal,\n"
2431 "uniform sampler2D Texture_SecondaryGloss,\n"
2432 "#endif\n"
2433 "#ifdef USEOFFSETMAPPING\n"
2434 "uniform float OffsetMapping_Scale,\n"
2435 "#endif\n"
2436 "uniform half SpecularPower,\n"
2437 "out float4 gl_FragColor : COLOR\n"
2438 ")\n"
2439 "{\n"
2440 "       float2 TexCoord = TexCoordBoth.xy;\n"
2441 "#ifdef USEOFFSETMAPPING\n"
2442 "       // apply offsetmapping\n"
2443 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2444 "#define TexCoord TexCoordOffset\n"
2445 "#endif\n"
2446 "\n"
2447 "#ifdef USEALPHAKILL\n"
2448 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2449 "               discard;\n"
2450 "#endif\n"
2451 "\n"
2452 "#ifdef USEVERTEXTEXTUREBLEND\n"
2453 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2454 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2455 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2456 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2457 "#endif\n"
2458 "\n"
2459 "#ifdef USEVERTEXTEXTUREBLEND\n"
2460 "       float3 surfacenormal = lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
2461 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2462 "#else\n"
2463 "       float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
2464 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2465 "#endif\n"
2466 "\n"
2467 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), 1);\n"
2468 "}\n"
2469 "#endif // FRAGMENT_SHADER\n"
2470 "#else // !MODE_DEFERREDGEOMETRY\n"
2471 "\n"
2472 "\n"
2473 "\n"
2474 "\n"
2475 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2476 "#ifdef VERTEX_SHADER\n"
2477 "void main\n"
2478 "(\n"
2479 "float4 gl_Vertex : POSITION,\n"
2480 "uniform float4x4 ModelViewProjectionMatrix,\n"
2481 "uniform float4x4 ModelViewMatrix,\n"
2482 "out float4 gl_Position : POSITION,\n"
2483 "out float4 ModelViewPosition : TEXCOORD0\n"
2484 ")\n"
2485 "{\n"
2486 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2487 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2488 "}\n"
2489 "#endif // VERTEX_SHADER\n"
2490 "\n"
2491 "#ifdef FRAGMENT_SHADER\n"
2492 "void main\n"
2493 "(\n"
2494 "float2 Pixel : WPOS,\n"
2495 "float4 ModelViewPosition : TEXCOORD0,\n"
2496 "uniform float4x4 ViewToLight,\n"
2497 "uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2498 "uniform float3 LightPosition,\n"
2499 "uniform half2 PixelToScreenTexCoord,\n"
2500 "uniform half3 DeferredColor_Ambient,\n"
2501 "uniform half3 DeferredColor_Diffuse,\n"
2502 "#ifdef USESPECULAR\n"
2503 "uniform half3 DeferredColor_Specular,\n"
2504 "uniform half SpecularPower,\n"
2505 "#endif\n"
2506 "uniform sampler2D Texture_Attenuation,\n"
2507 "uniform sampler2D Texture_ScreenDepth,\n"
2508 "uniform sampler2D Texture_ScreenNormalMap,\n"
2509 "\n"
2510 "#ifdef USESHADOWMAPRECT\n"
2511 "# ifdef USESHADOWSAMPLER\n"
2512 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2513 "# else\n"
2514 "uniform samplerRECT Texture_ShadowMapRect,\n"
2515 "# endif\n"
2516 "#endif\n"
2517 "\n"
2518 "#ifdef USESHADOWMAP2D\n"
2519 "# ifdef USESHADOWSAMPLER\n"
2520 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2521 "# else\n"
2522 "uniform sampler2D Texture_ShadowMap2D,\n"
2523 "# endif\n"
2524 "#endif\n"
2525 "\n"
2526 "#ifdef USESHADOWMAPVSDCT\n"
2527 "uniform samplerCUBE Texture_CubeProjection,\n"
2528 "#endif\n"
2529 "\n"
2530 "#ifdef USESHADOWMAPCUBE\n"
2531 "# ifdef USESHADOWSAMPLER\n"
2532 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2533 "# else\n"
2534 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2535 "# endif\n"
2536 "#endif\n"
2537 "\n"
2538 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2539 "uniform float2 ShadowMap_TextureScale,\n"
2540 "uniform float4 ShadowMap_Parameters,\n"
2541 "#endif\n"
2542 "\n"
2543 "out float4 gl_FragData0 : COLOR0,\n"
2544 "out float4 gl_FragData1 : COLOR1\n"
2545 ")\n"
2546 "{\n"
2547 "       // calculate viewspace pixel position\n"
2548 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2549 "       ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2550 "       float3 position;\n"
2551 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2552 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2553 "       // decode viewspace pixel normal\n"
2554 "       half4 normalmap = tex2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
2555 "       half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
2556 "       // surfacenormal = pixel normal in viewspace\n"
2557 "       // LightVector = pixel to light in viewspace\n"
2558 "       // CubeVector = position in lightspace\n"
2559 "       // eyevector = pixel to view in viewspace\n"
2560 "       float3 CubeVector = float3(mul(ViewToLight, float4(position,1)));\n"
2561 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2562 "#ifdef USEDIFFUSE\n"
2563 "       // calculate diffuse shading\n"
2564 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2565 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2566 "#endif\n"
2567 "#ifdef USESPECULAR\n"
2568 "       // calculate directional shading\n"
2569 "       float3 eyevector = position * -1.0;\n"
2570 "#  ifdef USEEXACTSPECULARMATH\n"
2571 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
2572 "#  else\n"
2573 "       half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
2574 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
2575 "#  endif\n"
2576 "#endif\n"
2577 "\n"
2578 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2579 "       fade *= ShadowMapCompare(CubeVector,\n"
2580 "# if defined(USESHADOWMAP2D)\n"
2581 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2582 "# endif\n"
2583 "# if defined(USESHADOWMAPRECT)\n"
2584 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2585 "# endif\n"
2586 "# if defined(USESHADOWMAPCUBE)\n"
2587 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2588 "# endif\n"
2589 "\n"
2590 "#ifdef USESHADOWMAPVSDCT\n"
2591 ", Texture_CubeProjection\n"
2592 "#endif\n"
2593 "       );\n"
2594 "#endif\n"
2595 "\n"
2596 "#ifdef USEDIFFUSE\n"
2597 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2598 "#else\n"
2599 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2600 "#endif\n"
2601 "#ifdef USESPECULAR\n"
2602 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2603 "#else\n"
2604 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2605 "#endif\n"
2606 "\n"
2607 "# ifdef USECUBEFILTER\n"
2608 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2609 "       gl_FragData0.rgb *= cubecolor;\n"
2610 "       gl_FragData1.rgb *= cubecolor;\n"
2611 "# endif\n"
2612 "}\n"
2613 "#endif // FRAGMENT_SHADER\n"
2614 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2615 "\n"
2616 "\n"
2617 "\n"
2618 "\n"
2619 "#ifdef VERTEX_SHADER\n"
2620 "void main\n"
2621 "(\n"
2622 "float4 gl_Vertex : POSITION,\n"
2623 "uniform float4x4 ModelViewProjectionMatrix,\n"
2624 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2625 "float4 gl_Color : COLOR0,\n"
2626 "#endif\n"
2627 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2628 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2629 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2630 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2631 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2632 "\n"
2633 "uniform float3 EyePosition,\n"
2634 "uniform float4x4 TexMatrix,\n"
2635 "#ifdef USEVERTEXTEXTUREBLEND\n"
2636 "uniform float4x4 BackgroundTexMatrix,\n"
2637 "#endif\n"
2638 "#ifdef MODE_LIGHTSOURCE\n"
2639 "uniform float4x4 ModelToLight,\n"
2640 "#endif\n"
2641 "#ifdef MODE_LIGHTSOURCE\n"
2642 "uniform float3 LightPosition,\n"
2643 "#endif\n"
2644 "#ifdef MODE_LIGHTDIRECTION\n"
2645 "uniform float3 LightDir,\n"
2646 "#endif\n"
2647 "uniform float4 FogPlane,\n"
2648 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2649 "uniform float3 LightPosition,\n"
2650 "#endif\n"
2651 "#ifdef USESHADOWMAPORTHO\n"
2652 "uniform float4x4 ShadowMapMatrix,\n"
2653 "#endif\n"
2654 "\n"
2655 "out float4 gl_FrontColor : COLOR,\n"
2656 "out float4 TexCoordBoth : TEXCOORD0,\n"
2657 "#ifdef USELIGHTMAP\n"
2658 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2659 "#endif\n"
2660 "#ifdef USEEYEVECTOR\n"
2661 "out float3 EyeVector : TEXCOORD2,\n"
2662 "#endif\n"
2663 "#ifdef USEREFLECTION\n"
2664 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2665 "#endif\n"
2666 "#ifdef USEFOG\n"
2667 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2668 "#endif\n"
2669 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2670 "out float3 LightVector : TEXCOORD1,\n"
2671 "#endif\n"
2672 "#ifdef MODE_LIGHTSOURCE\n"
2673 "out float3 CubeVector : TEXCOORD3,\n"
2674 "#endif\n"
2675 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2676 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2677 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2678 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2679 "#endif\n"
2680 "#ifdef USESHADOWMAPORTHO\n"
2681 "out float3 ShadowMapTC : TEXCOORD8,\n"
2682 "#endif\n"
2683 "out float4 gl_Position : POSITION\n"
2684 ")\n"
2685 "{\n"
2686 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2687 "       gl_FrontColor = gl_Color;\n"
2688 "#endif\n"
2689 "       // copy the surface texcoord\n"
2690 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2691 "#ifdef USEVERTEXTEXTUREBLEND\n"
2692 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2693 "#endif\n"
2694 "#ifdef USELIGHTMAP\n"
2695 "       TexCoordLightmap = float2(gl_MultiTexCoord4);\n"
2696 "#endif\n"
2697 "\n"
2698 "#ifdef MODE_LIGHTSOURCE\n"
2699 "       // transform vertex position into light attenuation/cubemap space\n"
2700 "       // (-1 to +1 across the light box)\n"
2701 "       CubeVector = float3(mul(ModelToLight, gl_Vertex));\n"
2702 "\n"
2703 "# ifdef USEDIFFUSE\n"
2704 "       // transform unnormalized light direction into tangent space\n"
2705 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2706 "       //  normalize it per pixel)\n"
2707 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2708 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2709 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2710 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2711 "# endif\n"
2712 "#endif\n"
2713 "\n"
2714 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2715 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2716 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2717 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2718 "#endif\n"
2719 "\n"
2720 "       // transform unnormalized eye direction into tangent space\n"
2721 "#ifdef USEEYEVECTOR\n"
2722 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2723 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2724 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2725 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2726 "#endif\n"
2727 "\n"
2728 "#ifdef USEFOG\n"
2729 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2730 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2731 "#endif\n"
2732 "\n"
2733 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2734 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2735 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2736 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2737 "#endif\n"
2738 "\n"
2739 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2740 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2741 "\n"
2742 "#ifdef USESHADOWMAPORTHO\n"
2743 "       ShadowMapTC = float3(mul(ShadowMapMatrix, gl_Position));\n"
2744 "#endif\n"
2745 "\n"
2746 "#ifdef USEREFLECTION\n"
2747 "       ModelViewProjectionPosition = gl_Position;\n"
2748 "#endif\n"
2749 "}\n"
2750 "#endif // VERTEX_SHADER\n"
2751 "\n"
2752 "\n"
2753 "\n"
2754 "\n"
2755 "#ifdef FRAGMENT_SHADER\n"
2756 "void main\n"
2757 "(\n"
2758 "#ifdef USEDEFERREDLIGHTMAP\n"
2759 "float2 Pixel : WPOS,\n"
2760 "#endif\n"
2761 "float4 gl_FrontColor : COLOR,\n"
2762 "float4 TexCoordBoth : TEXCOORD0,\n"
2763 "#ifdef USELIGHTMAP\n"
2764 "float2 TexCoordLightmap : TEXCOORD1,\n"
2765 "#endif\n"
2766 "#ifdef USEEYEVECTOR\n"
2767 "float3 EyeVector : TEXCOORD2,\n"
2768 "#endif\n"
2769 "#ifdef USEREFLECTION\n"
2770 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2771 "#endif\n"
2772 "#ifdef USEFOG\n"
2773 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2774 "#endif\n"
2775 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2776 "float3 LightVector : TEXCOORD1,\n"
2777 "#endif\n"
2778 "#ifdef MODE_LIGHTSOURCE\n"
2779 "float3 CubeVector : TEXCOORD3,\n"
2780 "#endif\n"
2781 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2782 "float4 ModelViewPosition : TEXCOORD0,\n"
2783 "#endif\n"
2784 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2785 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2786 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2787 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2788 "#endif\n"
2789 "#ifdef USESHADOWMAPORTHO\n"
2790 "float3 ShadowMapTC : TEXCOORD8,\n"
2791 "#endif\n"
2792 "\n"
2793 "uniform sampler2D Texture_Normal,\n"
2794 "uniform sampler2D Texture_Color,\n"
2795 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2796 "uniform sampler2D Texture_Gloss,\n"
2797 "#endif\n"
2798 "#ifdef USEGLOW\n"
2799 "uniform sampler2D Texture_Glow,\n"
2800 "#endif\n"
2801 "#ifdef USEVERTEXTEXTUREBLEND\n"
2802 "uniform sampler2D Texture_SecondaryNormal,\n"
2803 "uniform sampler2D Texture_SecondaryColor,\n"
2804 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2805 "uniform sampler2D Texture_SecondaryGloss,\n"
2806 "#endif\n"
2807 "#ifdef USEGLOW\n"
2808 "uniform sampler2D Texture_SecondaryGlow,\n"
2809 "#endif\n"
2810 "#endif\n"
2811 "#ifdef USECOLORMAPPING\n"
2812 "uniform sampler2D Texture_Pants,\n"
2813 "uniform sampler2D Texture_Shirt,\n"
2814 "#endif\n"
2815 "#ifdef USEFOG\n"
2816 "uniform sampler2D Texture_FogMask,\n"
2817 "#endif\n"
2818 "#ifdef USELIGHTMAP\n"
2819 "uniform sampler2D Texture_Lightmap,\n"
2820 "#endif\n"
2821 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2822 "uniform sampler2D Texture_Deluxemap,\n"
2823 "#endif\n"
2824 "#ifdef USEREFLECTION\n"
2825 "uniform sampler2D Texture_Reflection,\n"
2826 "#endif\n"
2827 "\n"
2828 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2829 "uniform sampler2D Texture_ScreenDepth,\n"
2830 "uniform sampler2D Texture_ScreenNormalMap,\n"
2831 "#endif\n"
2832 "#ifdef USEDEFERREDLIGHTMAP\n"
2833 "uniform sampler2D Texture_ScreenDiffuse,\n"
2834 "uniform sampler2D Texture_ScreenSpecular,\n"
2835 "#endif\n"
2836 "\n"
2837 "#ifdef USECOLORMAPPING\n"
2838 "uniform half3 Color_Pants,\n"
2839 "uniform half3 Color_Shirt,\n"
2840 "#endif\n"
2841 "#ifdef USEFOG\n"
2842 "uniform float3 FogColor,\n"
2843 "uniform float FogRangeRecip,\n"
2844 "uniform float FogPlaneViewDist,\n"
2845 "uniform float FogHeightFade,\n"
2846 "#endif\n"
2847 "\n"
2848 "#ifdef USEOFFSETMAPPING\n"
2849 "uniform float OffsetMapping_Scale,\n"
2850 "#endif\n"
2851 "\n"
2852 "#ifdef USEDEFERREDLIGHTMAP\n"
2853 "uniform half2 PixelToScreenTexCoord,\n"
2854 "uniform half3 DeferredMod_Diffuse,\n"
2855 "uniform half3 DeferredMod_Specular,\n"
2856 "#endif\n"
2857 "uniform half3 Color_Ambient,\n"
2858 "uniform half3 Color_Diffuse,\n"
2859 "uniform half3 Color_Specular,\n"
2860 "uniform half SpecularPower,\n"
2861 "#ifdef USEGLOW\n"
2862 "uniform half3 Color_Glow,\n"
2863 "#endif\n"
2864 "uniform half Alpha,\n"
2865 "#ifdef USEREFLECTION\n"
2866 "uniform float4 DistortScaleRefractReflect,\n"
2867 "uniform float4 ScreenScaleRefractReflect,\n"
2868 "uniform float4 ScreenCenterRefractReflect,\n"
2869 "uniform half4 ReflectColor,\n"
2870 "#endif\n"
2871 "#ifdef USEREFLECTCUBE\n"
2872 "uniform float4x4 ModelToReflectCube,\n"
2873 "uniform sampler2D Texture_ReflectMask,\n"
2874 "uniform samplerCUBE Texture_ReflectCube,\n"
2875 "#endif\n"
2876 "#ifdef MODE_LIGHTDIRECTION\n"
2877 "uniform half3 LightColor,\n"
2878 "#endif\n"
2879 "#ifdef MODE_LIGHTSOURCE\n"
2880 "uniform half3 LightColor,\n"
2881 "#endif\n"
2882 "\n"
2883 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2884 "uniform sampler2D Texture_Attenuation,\n"
2885 "uniform samplerCUBE Texture_Cube,\n"
2886 "#endif\n"
2887 "\n"
2888 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2889 "\n"
2890 "#ifdef USESHADOWMAPRECT\n"
2891 "# ifdef USESHADOWSAMPLER\n"
2892 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2893 "# else\n"
2894 "uniform samplerRECT Texture_ShadowMapRect,\n"
2895 "# endif\n"
2896 "#endif\n"
2897 "\n"
2898 "#ifdef USESHADOWMAP2D\n"
2899 "# ifdef USESHADOWSAMPLER\n"
2900 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2901 "# else\n"
2902 "uniform sampler2D Texture_ShadowMap2D,\n"
2903 "# endif\n"
2904 "#endif\n"
2905 "\n"
2906 "#ifdef USESHADOWMAPVSDCT\n"
2907 "uniform samplerCUBE Texture_CubeProjection,\n"
2908 "#endif\n"
2909 "\n"
2910 "#ifdef USESHADOWMAPCUBE\n"
2911 "# ifdef USESHADOWSAMPLER\n"
2912 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2913 "# else\n"
2914 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2915 "# endif\n"
2916 "#endif\n"
2917 "\n"
2918 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2919 "uniform float2 ShadowMap_TextureScale,\n"
2920 "uniform float4 ShadowMap_Parameters,\n"
2921 "#endif\n"
2922 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2923 "\n"
2924 "out float4 gl_FragColor : COLOR\n"
2925 ")\n"
2926 "{\n"
2927 "       float2 TexCoord = TexCoordBoth.xy;\n"
2928 "#ifdef USEVERTEXTEXTUREBLEND\n"
2929 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
2930 "#endif\n"
2931 "#ifdef USEOFFSETMAPPING\n"
2932 "       // apply offsetmapping\n"
2933 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2934 "#define TexCoord TexCoordOffset\n"
2935 "#endif\n"
2936 "\n"
2937 "       // combine the diffuse textures (base, pants, shirt)\n"
2938 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
2939 "#ifdef USEALPHAKILL\n"
2940 "       if (color.a < 0.5)\n"
2941 "               discard;\n"
2942 "#endif\n"
2943 "       color.a *= Alpha;\n"
2944 "#ifdef USECOLORMAPPING\n"
2945 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord)) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
2946 "#endif\n"
2947 "#ifdef USEVERTEXTEXTUREBLEND\n"
2948 "       float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
2949 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
2950 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
2951 "       color.rgb = half3(lerp(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
2952 "       color.a = 1.0;\n"
2953 "       //color = lerp(half4(1, 0, 0, 1), color, terrainblend);\n"
2954 "#endif\n"
2955 "\n"
2956 "       // get the surface normal\n"
2957 "#ifdef USEVERTEXTEXTUREBLEND\n"
2958 "       half3 surfacenormal = normalize(half3(lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
2959 "#else\n"
2960 "       half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
2961 "#endif\n"
2962 "\n"
2963 "       // get the material colors\n"
2964 "       half3 diffusetex = color.rgb;\n"
2965 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2966 "# ifdef USEVERTEXTEXTUREBLEND\n"
2967 "       half4 glosstex = half4(lerp(float4(tex2D(Texture_SecondaryGloss, TexCoord2)), float4(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
2968 "# else\n"
2969 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
2970 "# endif\n"
2971 "#endif\n"
2972 "\n"
2973 "#ifdef USEREFLECTCUBE\n"
2974 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
2975 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
2976 "       float3 ReflectCubeTexCoord = float3(mul(ModelToReflectCube, float4(ModelReflectVector, 0)));\n"
2977 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord)) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord));\n"
2978 "#endif\n"
2979 "\n"
2980 "\n"
2981 "\n"
2982 "\n"
2983 "#ifdef MODE_LIGHTSOURCE\n"
2984 "       // light source\n"
2985 "#ifdef USEDIFFUSE\n"
2986 "       half3 lightnormal = half3(normalize(LightVector));\n"
2987 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2988 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
2989 "#ifdef USESPECULAR\n"
2990 "#ifdef USEEXACTSPECULARMATH\n"
2991 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
2992 "#else\n"
2993 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
2994 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
2995 "#endif\n"
2996 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
2997 "#endif\n"
2998 "#else\n"
2999 "       color.rgb = diffusetex * Color_Ambient;\n"
3000 "#endif\n"
3001 "       color.rgb *= LightColor;\n"
3002 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
3003 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
3004 "       color.rgb *= ShadowMapCompare(CubeVector,\n"
3005 "# if defined(USESHADOWMAP2D)\n"
3006 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3007 "# endif\n"
3008 "# if defined(USESHADOWMAPRECT)\n"
3009 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3010 "# endif\n"
3011 "# if defined(USESHADOWMAPCUBE)\n"
3012 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
3013 "# endif\n"
3014 "\n"
3015 "#ifdef USESHADOWMAPVSDCT\n"
3016 ", Texture_CubeProjection\n"
3017 "#endif\n"
3018 "       );\n"
3019 "\n"
3020 "#endif\n"
3021 "# ifdef USECUBEFILTER\n"
3022 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector));\n"
3023 "# endif\n"
3024 "#endif // MODE_LIGHTSOURCE\n"
3025 "\n"
3026 "\n"
3027 "\n"
3028 "\n"
3029 "#ifdef MODE_LIGHTDIRECTION\n"
3030 "#define SHADING\n"
3031 "#ifdef USEDIFFUSE\n"
3032 "       half3 lightnormal = half3(normalize(LightVector));\n"
3033 "#endif\n"
3034 "#define lightcolor LightColor\n"
3035 "#endif // MODE_LIGHTDIRECTION\n"
3036 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3037 "#define SHADING\n"
3038 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3039 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3040 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3041 "       // convert modelspace light vector to tangentspace\n"
3042 "       half3 lightnormal;\n"
3043 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3044 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3045 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3046 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3047 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3048 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3049 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3050 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3051 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3052 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3053 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3054 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3055 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3056 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3057 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3058 "#define SHADING\n"
3059 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3060 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3061 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3062 "#endif\n"
3063 "\n"
3064 "\n"
3065 "\n"
3066 "\n"
3067 "#ifdef MODE_LIGHTMAP\n"
3068 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
3069 "#endif // MODE_LIGHTMAP\n"
3070 "#ifdef MODE_VERTEXCOLOR\n"
3071 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3072 "#endif // MODE_VERTEXCOLOR\n"
3073 "#ifdef MODE_FLATCOLOR\n"
3074 "       color.rgb = diffusetex * Color_Ambient;\n"
3075 "#endif // MODE_FLATCOLOR\n"
3076 "\n"
3077 "\n"
3078 "\n"
3079 "\n"
3080 "#ifdef SHADING\n"
3081 "# ifdef USEDIFFUSE\n"
3082 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3083 "#  ifdef USESPECULAR\n"
3084 "#   ifdef USEEXACTSPECULARMATH\n"
3085 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
3086 "#   else\n"
3087 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3088 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
3089 "#   endif\n"
3090 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3091 "#  else\n"
3092 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3093 "#  endif\n"
3094 "# else\n"
3095 "       color.rgb = diffusetex * Color_Ambient;\n"
3096 "# endif\n"
3097 "#endif\n"
3098 "\n"
3099 "#ifdef USESHADOWMAPORTHO\n"
3100 "       color.rgb *= ShadowMapCompare(ShadowMapTC,\n"
3101 "# if defined(USESHADOWMAP2D)\n"
3102 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3103 "# endif\n"
3104 "# if defined(USESHADOWMAPRECT)\n"
3105 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3106 "# endif\n"
3107 "       );\n"
3108 "#endif\n"
3109 "\n"
3110 "#ifdef USEDEFERREDLIGHTMAP\n"
3111 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3112 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
3113 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
3114 "#endif\n"
3115 "\n"
3116 "#ifdef USEGLOW\n"
3117 "#ifdef USEVERTEXTEXTUREBLEND\n"
3118 "       color.rgb += lerp(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
3119 "#else\n"
3120 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
3121 "#endif\n"
3122 "#endif\n"
3123 "\n"
3124 "#ifdef USEFOG\n"
3125 "#ifdef MODE_LIGHTSOURCE\n"
3126 "       color.rgb *= half(FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3127 "#else\n"
3128 "       color.rgb = lerp(FogColor, float3(color.rgb), FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3129 "#endif\n"
3130 "#endif\n"
3131 "\n"
3132 "       // 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"
3133 "#ifdef USEREFLECTION\n"
3134 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3135 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3136 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3137 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
3138 "       // FIXME temporary hack to detect the case that the reflection\n"
3139 "       // gets blackened at edges due to leaving the area that contains actual\n"
3140 "       // content.\n"
3141 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3142 "       // 'appening.\n"
3143 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3144 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3145 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3146 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3147 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3148 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
3149 "#endif\n"
3150 "\n"
3151 "       gl_FragColor = float4(color);\n"
3152 "}\n"
3153 "#endif // FRAGMENT_SHADER\n"
3154 "\n"
3155 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3156 "#endif // !MODE_DEFERREDGEOMETRY\n"
3157 "#endif // !MODE_WATER\n"
3158 "#endif // !MODE_REFRACTION\n"
3159 "#endif // !MODE_BLOOMBLUR\n"
3160 "#endif // !MODE_GENERIC\n"
3161 "#endif // !MODE_POSTPROCESS\n"
3162 "#endif // !MODE_SHOWDEPTH\n"
3163 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3164 ;
3165
3166 char *glslshaderstring = NULL;
3167 char *cgshaderstring = NULL;
3168
3169 //=======================================================================================================================================================
3170
3171 typedef struct shaderpermutationinfo_s
3172 {
3173         const char *pretext;
3174         const char *name;
3175 }
3176 shaderpermutationinfo_t;
3177
3178 typedef struct shadermodeinfo_s
3179 {
3180         const char *vertexfilename;
3181         const char *geometryfilename;
3182         const char *fragmentfilename;
3183         const char *pretext;
3184         const char *name;
3185 }
3186 shadermodeinfo_t;
3187
3188 typedef enum shaderpermutation_e
3189 {
3190         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3191         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3192         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3193         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3194         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3195         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3196         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3197         SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
3198         SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
3199         SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
3200         SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
3201         SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
3202         SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
3203         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3204         SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3205         SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3206         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3207         SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
3208         SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
3209         SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
3210         SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
3211         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3212         SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
3213         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3214         SHADERPERMUTATION_SHADOWMAPORTHO = 1<<24, //< (lightsource) use orthographic shadowmap projection
3215         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<25, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3216         SHADERPERMUTATION_ALPHAKILL = 1<<26, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3217         SHADERPERMUTATION_REFLECTCUBE = 1<<27, ///< fake reflections using global cubemap (not HDRI light probe)
3218         SHADERPERMUTATION_LIMIT = 1<<28, ///< size of permutations array
3219         SHADERPERMUTATION_COUNT = 28 ///< size of shaderpermutationinfo array
3220 }
3221 shaderpermutation_t;
3222
3223 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3224 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3225 {
3226         {"#define USEDIFFUSE\n", " diffuse"},
3227         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3228         {"#define USEVIEWTINT\n", " viewtint"},
3229         {"#define USECOLORMAPPING\n", " colormapping"},
3230         {"#define USESATURATION\n", " saturation"},
3231         {"#define USEFOGINSIDE\n", " foginside"},
3232         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3233         {"#define USEGAMMARAMPS\n", " gammaramps"},
3234         {"#define USECUBEFILTER\n", " cubefilter"},
3235         {"#define USEGLOW\n", " glow"},
3236         {"#define USEBLOOM\n", " bloom"},
3237         {"#define USESPECULAR\n", " specular"},
3238         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3239         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3240         {"#define USEREFLECTION\n", " reflection"},
3241         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3242         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3243         {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3244         {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3245         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3246         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3247         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3248         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3249         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3250         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3251         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3252         {"#define USEALPHAKILL\n", " alphakill"},
3253         {"#define USEREFLECTCUBE\n", " reflectcube"},
3254 };
3255
3256 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3257 typedef enum shadermode_e
3258 {
3259         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3260         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3261         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3262         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3263         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3264         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3265         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3266         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3267         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3268         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3269         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3270         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3271         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3272         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3273         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3274         SHADERMODE_COUNT
3275 }
3276 shadermode_t;
3277
3278 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3279 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3280 {
3281         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3282         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3283         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3284         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3285         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3286         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3287         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3288         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3289         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3290         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3291         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3292         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3293         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3294         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3295         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3296 };
3297
3298 #ifdef SUPPORTCG
3299 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3300 {
3301         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3302         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3303         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3304         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3305         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3306         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3307         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3308         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3309         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3310         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3311         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3312         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3313         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3314         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3315         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3316 };
3317 #endif
3318
3319 struct r_glsl_permutation_s;
3320 typedef struct r_glsl_permutation_s
3321 {
3322         /// hash lookup data
3323         struct r_glsl_permutation_s *hashnext;
3324         unsigned int mode;
3325         unsigned int permutation;
3326
3327         /// indicates if we have tried compiling this permutation already
3328         qboolean compiled;
3329         /// 0 if compilation failed
3330         int program;
3331         /// locations of detected uniforms in program object, or -1 if not found
3332         int loc_Texture_First;
3333         int loc_Texture_Second;
3334         int loc_Texture_GammaRamps;
3335         int loc_Texture_Normal;
3336         int loc_Texture_Color;
3337         int loc_Texture_Gloss;
3338         int loc_Texture_Glow;
3339         int loc_Texture_SecondaryNormal;
3340         int loc_Texture_SecondaryColor;
3341         int loc_Texture_SecondaryGloss;
3342         int loc_Texture_SecondaryGlow;
3343         int loc_Texture_Pants;
3344         int loc_Texture_Shirt;
3345         int loc_Texture_FogMask;
3346         int loc_Texture_Lightmap;
3347         int loc_Texture_Deluxemap;
3348         int loc_Texture_Attenuation;
3349         int loc_Texture_Cube;
3350         int loc_Texture_Refraction;
3351         int loc_Texture_Reflection;
3352         int loc_Texture_ShadowMapRect;
3353         int loc_Texture_ShadowMapCube;
3354         int loc_Texture_ShadowMap2D;
3355         int loc_Texture_CubeProjection;
3356         int loc_Texture_ScreenDepth;
3357         int loc_Texture_ScreenNormalMap;
3358         int loc_Texture_ScreenDiffuse;
3359         int loc_Texture_ScreenSpecular;
3360         int loc_Texture_ReflectMask;
3361         int loc_Texture_ReflectCube;
3362         int loc_Alpha;
3363         int loc_BloomBlur_Parameters;
3364         int loc_ClientTime;
3365         int loc_Color_Ambient;
3366         int loc_Color_Diffuse;
3367         int loc_Color_Specular;
3368         int loc_Color_Glow;
3369         int loc_Color_Pants;
3370         int loc_Color_Shirt;
3371         int loc_DeferredColor_Ambient;
3372         int loc_DeferredColor_Diffuse;
3373         int loc_DeferredColor_Specular;
3374         int loc_DeferredMod_Diffuse;
3375         int loc_DeferredMod_Specular;
3376         int loc_DistortScaleRefractReflect;
3377         int loc_EyePosition;
3378         int loc_FogColor;
3379         int loc_FogHeightFade;
3380         int loc_FogPlane;
3381         int loc_FogPlaneViewDist;
3382         int loc_FogRangeRecip;
3383         int loc_LightColor;
3384         int loc_LightDir;
3385         int loc_LightPosition;
3386         int loc_OffsetMapping_Scale;
3387         int loc_PixelSize;
3388         int loc_ReflectColor;
3389         int loc_ReflectFactor;
3390         int loc_ReflectOffset;
3391         int loc_RefractColor;
3392         int loc_Saturation;
3393         int loc_ScreenCenterRefractReflect;
3394         int loc_ScreenScaleRefractReflect;
3395         int loc_ScreenToDepth;
3396         int loc_ShadowMap_Parameters;
3397         int loc_ShadowMap_TextureScale;
3398         int loc_SpecularPower;
3399         int loc_UserVec1;
3400         int loc_UserVec2;
3401         int loc_UserVec3;
3402         int loc_UserVec4;
3403         int loc_ViewTintColor;
3404         int loc_ViewToLight;
3405         int loc_ModelToLight;
3406         int loc_TexMatrix;
3407         int loc_BackgroundTexMatrix;
3408         int loc_ModelViewProjectionMatrix;
3409         int loc_ModelViewMatrix;
3410         int loc_PixelToScreenTexCoord;
3411         int loc_ModelToReflectCube;
3412         int loc_ShadowMapMatrix;        
3413 }
3414 r_glsl_permutation_t;
3415
3416 #define SHADERPERMUTATION_HASHSIZE 256
3417
3418 /// information about each possible shader permutation
3419 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3420 /// currently selected permutation
3421 r_glsl_permutation_t *r_glsl_permutation;
3422 /// storage for permutations linked in the hash table
3423 memexpandablearray_t r_glsl_permutationarray;
3424
3425 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3426 {
3427         //unsigned int hashdepth = 0;
3428         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3429         r_glsl_permutation_t *p;
3430         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3431         {
3432                 if (p->mode == mode && p->permutation == permutation)
3433                 {
3434                         //if (hashdepth > 10)
3435                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3436                         return p;
3437                 }
3438                 //hashdepth++;
3439         }
3440         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3441         p->mode = mode;
3442         p->permutation = permutation;
3443         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3444         r_glsl_permutationhash[mode][hashindex] = p;
3445         //if (hashdepth > 10)
3446         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3447         return p;
3448 }
3449
3450 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3451 {
3452         char *shaderstring;
3453         if (!filename || !filename[0])
3454                 return NULL;
3455         if (!strcmp(filename, "glsl/default.glsl"))
3456         {
3457                 if (!glslshaderstring)
3458                 {
3459                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3460                         if (glslshaderstring)
3461                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3462                         else
3463                                 glslshaderstring = (char *)builtinshaderstring;
3464                 }
3465                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3466                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3467                 return shaderstring;
3468         }
3469         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3470         if (shaderstring)
3471         {
3472                 if (printfromdisknotice)
3473                         Con_DPrintf("from disk %s... ", filename);
3474                 return shaderstring;
3475         }
3476         return shaderstring;
3477 }
3478
3479 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3480 {
3481         int i;
3482         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3483         int vertstrings_count = 0;
3484         int geomstrings_count = 0;
3485         int fragstrings_count = 0;
3486         char *vertexstring, *geometrystring, *fragmentstring;
3487         const char *vertstrings_list[32+3];
3488         const char *geomstrings_list[32+3];
3489         const char *fragstrings_list[32+3];
3490         char permutationname[256];
3491
3492         if (p->compiled)
3493                 return;
3494         p->compiled = true;
3495         p->program = 0;
3496
3497         permutationname[0] = 0;
3498         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3499         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3500         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3501
3502         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3503
3504         // the first pretext is which type of shader to compile as
3505         // (later these will all be bound together as a program object)
3506         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3507         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3508         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3509
3510         // the second pretext is the mode (for example a light source)
3511         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3512         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3513         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3514         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3515
3516         // now add all the permutation pretexts
3517         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3518         {
3519                 if (permutation & (1<<i))
3520                 {
3521                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3522                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3523                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3524                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3525                 }
3526                 else
3527                 {
3528                         // keep line numbers correct
3529                         vertstrings_list[vertstrings_count++] = "\n";
3530                         geomstrings_list[geomstrings_count++] = "\n";
3531                         fragstrings_list[fragstrings_count++] = "\n";
3532                 }
3533         }
3534
3535         // now append the shader text itself
3536         vertstrings_list[vertstrings_count++] = vertexstring;
3537         geomstrings_list[geomstrings_count++] = geometrystring;
3538         fragstrings_list[fragstrings_count++] = fragmentstring;
3539
3540         // if any sources were NULL, clear the respective list
3541         if (!vertexstring)
3542                 vertstrings_count = 0;
3543         if (!geometrystring)
3544                 geomstrings_count = 0;
3545         if (!fragmentstring)
3546                 fragstrings_count = 0;
3547
3548         // compile the shader program
3549         if (vertstrings_count + geomstrings_count + fragstrings_count)
3550                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3551         if (p->program)
3552         {
3553                 CHECKGLERROR
3554                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3555                 // look up all the uniform variable names we care about, so we don't
3556                 // have to look them up every time we set them
3557
3558                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3559                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3560                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3561                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3562                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3563                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3564                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3565                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3566                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3567                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3568                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3569                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3570                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3571                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3572                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3573                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3574                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3575                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3576                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3577                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3578                 p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3579                 p->loc_Texture_ShadowMapCube      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3580                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3581                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3582                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3583                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3584                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3585                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3586                 p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3587                 p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3588                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3589                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3590                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3591                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3592                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3593                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3594                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3595                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3596                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3597                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3598                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3599                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3600                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3601                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3602                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3603                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3604                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3605                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3606                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3607                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3608                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3609                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3610                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3611                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3612                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3613                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3614                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3615                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3616                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3617                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3618                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3619                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3620                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3621                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3622                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3623                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3624                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3625                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3626                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3627                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3628                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3629                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3630                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3631                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3632                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3633                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3634                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3635                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3636                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3637                 p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3638                 p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");            
3639                 // initialize the samplers to refer to the texture units we use
3640                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3641                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3642                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3643                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3644                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3645                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3646                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3647                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3648                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3649                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3650                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3651                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3652                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3653                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3654                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3655                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3656                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3657                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3658                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3659                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3660                 if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT);
3661                 if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
3662                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D);
3663                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3664                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3665                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3666                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3667                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3668                 if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
3669                 if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
3670                 CHECKGLERROR
3671                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3672         }
3673         else
3674                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3675
3676         // free the strings
3677         if (vertexstring)
3678                 Mem_Free(vertexstring);
3679         if (geometrystring)
3680                 Mem_Free(geometrystring);
3681         if (fragmentstring)
3682                 Mem_Free(fragmentstring);
3683 }
3684
3685 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3686 {
3687         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3688         if (r_glsl_permutation != perm)
3689         {
3690                 r_glsl_permutation = perm;
3691                 if (!r_glsl_permutation->program)
3692                 {
3693                         if (!r_glsl_permutation->compiled)
3694                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3695                         if (!r_glsl_permutation->program)
3696                         {
3697                                 // remove features until we find a valid permutation
3698                                 int i;
3699                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3700                                 {
3701                                         // reduce i more quickly whenever it would not remove any bits
3702                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3703                                         if (!(permutation & j))
3704                                                 continue;
3705                                         permutation -= j;
3706                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3707                                         if (!r_glsl_permutation->compiled)
3708                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3709                                         if (r_glsl_permutation->program)
3710                                                 break;
3711                                 }
3712                                 if (i >= SHADERPERMUTATION_COUNT)
3713                                 {
3714                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3715                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3716                                         qglUseProgramObjectARB(0);CHECKGLERROR
3717                                         return; // no bit left to clear, entire mode is broken
3718                                 }
3719                         }
3720                 }
3721                 CHECKGLERROR
3722                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3723         }
3724         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3725         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3726         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3727 }
3728
3729 #ifdef SUPPORTCG
3730 #include <Cg/cgGL.h>
3731 struct r_cg_permutation_s;
3732 typedef struct r_cg_permutation_s
3733 {
3734         /// hash lookup data
3735         struct r_cg_permutation_s *hashnext;
3736         unsigned int mode;
3737         unsigned int permutation;
3738
3739         /// indicates if we have tried compiling this permutation already
3740         qboolean compiled;
3741         /// 0 if compilation failed
3742         CGprogram vprogram;
3743         CGprogram fprogram;
3744         /// locations of detected parameters in programs, or NULL if not found
3745         CGparameter vp_EyePosition;
3746         CGparameter vp_FogPlane;
3747         CGparameter vp_LightDir;
3748         CGparameter vp_LightPosition;
3749         CGparameter vp_ModelToLight;
3750         CGparameter vp_TexMatrix;
3751         CGparameter vp_BackgroundTexMatrix;
3752         CGparameter vp_ModelViewProjectionMatrix;
3753         CGparameter vp_ModelViewMatrix;
3754         CGparameter vp_ShadowMapMatrix;
3755
3756         CGparameter fp_Texture_First;
3757         CGparameter fp_Texture_Second;
3758         CGparameter fp_Texture_GammaRamps;
3759         CGparameter fp_Texture_Normal;
3760         CGparameter fp_Texture_Color;
3761         CGparameter fp_Texture_Gloss;
3762         CGparameter fp_Texture_Glow;
3763         CGparameter fp_Texture_SecondaryNormal;
3764         CGparameter fp_Texture_SecondaryColor;
3765         CGparameter fp_Texture_SecondaryGloss;
3766         CGparameter fp_Texture_SecondaryGlow;
3767         CGparameter fp_Texture_Pants;
3768         CGparameter fp_Texture_Shirt;
3769         CGparameter fp_Texture_FogMask;
3770         CGparameter fp_Texture_Lightmap;
3771         CGparameter fp_Texture_Deluxemap;
3772         CGparameter fp_Texture_Attenuation;
3773         CGparameter fp_Texture_Cube;
3774         CGparameter fp_Texture_Refraction;
3775         CGparameter fp_Texture_Reflection;
3776         CGparameter fp_Texture_ShadowMapRect;
3777         CGparameter fp_Texture_ShadowMapCube;
3778         CGparameter fp_Texture_ShadowMap2D;
3779         CGparameter fp_Texture_CubeProjection;
3780         CGparameter fp_Texture_ScreenDepth;
3781         CGparameter fp_Texture_ScreenNormalMap;
3782         CGparameter fp_Texture_ScreenDiffuse;
3783         CGparameter fp_Texture_ScreenSpecular;
3784         CGparameter fp_Texture_ReflectMask;
3785         CGparameter fp_Texture_ReflectCube;
3786         CGparameter fp_Alpha;
3787         CGparameter fp_BloomBlur_Parameters;
3788         CGparameter fp_ClientTime;
3789         CGparameter fp_Color_Ambient;
3790         CGparameter fp_Color_Diffuse;
3791         CGparameter fp_Color_Specular;
3792         CGparameter fp_Color_Glow;
3793         CGparameter fp_Color_Pants;
3794         CGparameter fp_Color_Shirt;
3795         CGparameter fp_DeferredColor_Ambient;
3796         CGparameter fp_DeferredColor_Diffuse;
3797         CGparameter fp_DeferredColor_Specular;
3798         CGparameter fp_DeferredMod_Diffuse;
3799         CGparameter fp_DeferredMod_Specular;
3800         CGparameter fp_DistortScaleRefractReflect;
3801         CGparameter fp_EyePosition;
3802         CGparameter fp_FogColor;
3803         CGparameter fp_FogHeightFade;
3804         CGparameter fp_FogPlane;
3805         CGparameter fp_FogPlaneViewDist;
3806         CGparameter fp_FogRangeRecip;
3807         CGparameter fp_LightColor;
3808         CGparameter fp_LightDir;
3809         CGparameter fp_LightPosition;
3810         CGparameter fp_OffsetMapping_Scale;
3811         CGparameter fp_PixelSize;
3812         CGparameter fp_ReflectColor;
3813         CGparameter fp_ReflectFactor;
3814         CGparameter fp_ReflectOffset;
3815         CGparameter fp_RefractColor;
3816         CGparameter fp_Saturation;
3817         CGparameter fp_ScreenCenterRefractReflect;
3818         CGparameter fp_ScreenScaleRefractReflect;
3819         CGparameter fp_ScreenToDepth;
3820         CGparameter fp_ShadowMap_Parameters;
3821         CGparameter fp_ShadowMap_TextureScale;
3822         CGparameter fp_SpecularPower;
3823         CGparameter fp_UserVec1;
3824         CGparameter fp_UserVec2;
3825         CGparameter fp_UserVec3;
3826         CGparameter fp_UserVec4;
3827         CGparameter fp_ViewTintColor;
3828         CGparameter fp_ViewToLight;
3829         CGparameter fp_PixelToScreenTexCoord;
3830         CGparameter fp_ModelToReflectCube;
3831 }
3832 r_cg_permutation_t;
3833
3834 /// information about each possible shader permutation
3835 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3836 /// currently selected permutation
3837 r_cg_permutation_t *r_cg_permutation;
3838 /// storage for permutations linked in the hash table
3839 memexpandablearray_t r_cg_permutationarray;
3840
3841 #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));}}
3842
3843 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3844 {
3845         //unsigned int hashdepth = 0;
3846         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3847         r_cg_permutation_t *p;
3848         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3849         {
3850                 if (p->mode == mode && p->permutation == permutation)
3851                 {
3852                         //if (hashdepth > 10)
3853                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3854                         return p;
3855                 }
3856                 //hashdepth++;
3857         }
3858         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3859         p->mode = mode;
3860         p->permutation = permutation;
3861         p->hashnext = r_cg_permutationhash[mode][hashindex];
3862         r_cg_permutationhash[mode][hashindex] = p;
3863         //if (hashdepth > 10)
3864         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3865         return p;
3866 }
3867
3868 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3869 {
3870         char *shaderstring;
3871         if (!filename || !filename[0])
3872                 return NULL;
3873         if (!strcmp(filename, "cg/default.cg"))
3874         {
3875                 if (!cgshaderstring)
3876                 {
3877                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3878                         if (cgshaderstring)
3879                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3880                         else
3881                                 cgshaderstring = (char *)builtincgshaderstring;
3882                 }
3883                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
3884                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
3885                 return shaderstring;
3886         }
3887         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3888         if (shaderstring)
3889         {
3890                 if (printfromdisknotice)
3891                         Con_DPrintf("from disk %s... ", filename);
3892                 return shaderstring;
3893         }
3894         return shaderstring;
3895 }
3896
3897 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
3898 {
3899         // TODO: load or create .fp and .vp shader files
3900 }
3901
3902 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
3903 {
3904         int i;
3905         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
3906         int vertstrings_count = 0, vertstring_length = 0;
3907         int geomstrings_count = 0, geomstring_length = 0;
3908         int fragstrings_count = 0, fragstring_length = 0;
3909         char *t;
3910         char *vertexstring, *geometrystring, *fragmentstring;
3911         char *vertstring, *geomstring, *fragstring;
3912         const char *vertstrings_list[32+3];
3913         const char *geomstrings_list[32+3];
3914         const char *fragstrings_list[32+3];
3915         char permutationname[256];
3916         char cachename[256];
3917         CGprofile vertexProfile;
3918         CGprofile fragmentProfile;
3919
3920         if (p->compiled)
3921                 return;
3922         p->compiled = true;
3923         p->vprogram = NULL;
3924         p->fprogram = NULL;
3925
3926         permutationname[0] = 0;
3927         cachename[0] = 0;
3928         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
3929         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
3930         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
3931
3932         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3933         strlcat(cachename, "cg/", sizeof(cachename));
3934
3935         // the first pretext is which type of shader to compile as
3936         // (later these will all be bound together as a program object)
3937         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3938         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3939         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3940
3941         // the second pretext is the mode (for example a light source)
3942         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3943         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3944         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3945         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3946         strlcat(cachename, modeinfo->name, sizeof(cachename));
3947
3948         // now add all the permutation pretexts
3949         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3950         {
3951                 if (permutation & (1<<i))
3952                 {
3953                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3954                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3955                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3956                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3957                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
3958                 }
3959                 else
3960                 {
3961                         // keep line numbers correct
3962                         vertstrings_list[vertstrings_count++] = "\n";
3963                         geomstrings_list[geomstrings_count++] = "\n";
3964                         fragstrings_list[fragstrings_count++] = "\n";
3965                 }
3966         }
3967
3968         // replace spaces in the cachename with _ characters
3969         for (i = 0;cachename[i];i++)
3970                 if (cachename[i] == ' ')
3971                         cachename[i] = '_';
3972
3973         // now append the shader text itself
3974         vertstrings_list[vertstrings_count++] = vertexstring;
3975         geomstrings_list[geomstrings_count++] = geometrystring;
3976         fragstrings_list[fragstrings_count++] = fragmentstring;
3977
3978         // if any sources were NULL, clear the respective list
3979         if (!vertexstring)
3980                 vertstrings_count = 0;
3981         if (!geometrystring)
3982                 geomstrings_count = 0;
3983         if (!fragmentstring)
3984                 fragstrings_count = 0;
3985
3986         vertstring_length = 0;
3987         for (i = 0;i < vertstrings_count;i++)
3988                 vertstring_length += strlen(vertstrings_list[i]);
3989         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
3990         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
3991                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
3992
3993         geomstring_length = 0;
3994         for (i = 0;i < geomstrings_count;i++)
3995                 geomstring_length += strlen(geomstrings_list[i]);
3996         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
3997         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
3998                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
3999
4000         fragstring_length = 0;
4001         for (i = 0;i < fragstrings_count;i++)
4002                 fragstring_length += strlen(fragstrings_list[i]);
4003         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4004         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4005                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4006
4007         CHECKGLERROR
4008         CHECKCGERROR
4009         //vertexProfile = CG_PROFILE_ARBVP1;
4010         //fragmentProfile = CG_PROFILE_ARBFP1;
4011         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4012         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4013         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4014         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4015         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4016         CHECKGLERROR
4017
4018         // try to load the cached shader, or generate one
4019         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4020
4021         // if caching failed, do a dynamic compile for now
4022         CHECKCGERROR
4023         if (vertstring[0] && !p->vprogram)
4024                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4025         CHECKCGERROR
4026         if (fragstring[0] && !p->fprogram)
4027                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4028         CHECKCGERROR
4029
4030         // look up all the uniform variable names we care about, so we don't
4031         // have to look them up every time we set them
4032         if (p->vprogram)
4033         {
4034                 CHECKCGERROR
4035                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4036                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4037                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4038                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4039                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4040                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4041                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4042                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4043                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4044                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4045                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4046                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4047                 CHECKCGERROR
4048         }
4049         if (p->fprogram)
4050         {
4051                 CHECKCGERROR
4052                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4053                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4054                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4055                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4056                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4057                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4058                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4059                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4060                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4061                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4062                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4063                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4064                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4065                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4066                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4067                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4068                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4069                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4070                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4071                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4072                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4073                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4074                 p->fp_Texture_ShadowMapRect      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
4075                 p->fp_Texture_ShadowMapCube      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
4076                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4077                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4078                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4079                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4080                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4081                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4082                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4083                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4084                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4085                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4086                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4087                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4088                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4089                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4090                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4091                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4092                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4093                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4094                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4095                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4096                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4097                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4098                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4099                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4100                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4101                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4102                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4103                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4104                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4105                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4106                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4107                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4108                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4109                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4110                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4111                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4112                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4113                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4114                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4115                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4116                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4117                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4118                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4119                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4120                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4121                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4122                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4123                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4124                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4125                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4126                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4127                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4128                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4129                 CHECKCGERROR
4130         }
4131
4132         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4133                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4134         else
4135                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4136
4137         // free the strings
4138         if (vertstring)
4139                 Mem_Free(vertstring);
4140         if (geomstring)
4141                 Mem_Free(geomstring);
4142         if (fragstring)
4143                 Mem_Free(fragstring);
4144         if (vertexstring)
4145                 Mem_Free(vertexstring);
4146         if (geometrystring)
4147                 Mem_Free(geometrystring);
4148         if (fragmentstring)
4149                 Mem_Free(fragmentstring);
4150 }
4151
4152 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4153 {
4154         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4155         CHECKGLERROR
4156         CHECKCGERROR
4157         if (r_cg_permutation != perm)
4158         {
4159                 r_cg_permutation = perm;
4160                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4161                 {
4162                         if (!r_cg_permutation->compiled)
4163                                 R_CG_CompilePermutation(perm, mode, permutation);
4164                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4165                         {
4166                                 // remove features until we find a valid permutation
4167                                 int i;
4168                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4169                                 {
4170                                         // reduce i more quickly whenever it would not remove any bits
4171                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4172                                         if (!(permutation & j))
4173                                                 continue;
4174                                         permutation -= j;
4175                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4176                                         if (!r_cg_permutation->compiled)
4177                                                 R_CG_CompilePermutation(perm, mode, permutation);
4178                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4179                                                 break;
4180                                 }
4181                                 if (i >= SHADERPERMUTATION_COUNT)
4182                                 {
4183                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4184                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4185                                         return; // no bit left to clear, entire mode is broken
4186                                 }
4187                         }
4188                 }
4189                 CHECKGLERROR
4190                 CHECKCGERROR
4191                 if (r_cg_permutation->vprogram)
4192                 {
4193                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4194                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4195                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4196                 }
4197                 else
4198                 {
4199                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4200                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4201                 }
4202                 if (r_cg_permutation->fprogram)
4203                 {
4204                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4205                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4206                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4207                 }
4208                 else
4209                 {
4210                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4211                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4212                 }
4213         }
4214         CHECKCGERROR
4215         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4216         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4217         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4218 }
4219
4220 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4221 {
4222         cgGLSetTextureParameter(param, R_GetTexture(tex));
4223         cgGLEnableTextureParameter(param);
4224 }
4225 #endif
4226
4227 void R_GLSL_Restart_f(void)
4228 {
4229         unsigned int i, limit;
4230         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4231                 Mem_Free(glslshaderstring);
4232         glslshaderstring = NULL;
4233         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4234                 Mem_Free(cgshaderstring);
4235         cgshaderstring = NULL;
4236         switch(vid.renderpath)
4237         {
4238         case RENDERPATH_GL20:
4239                 {
4240                         r_glsl_permutation_t *p;
4241                         r_glsl_permutation = NULL;
4242                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4243                         for (i = 0;i < limit;i++)
4244                         {
4245                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4246                                 {
4247                                         GL_Backend_FreeProgram(p->program);
4248                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4249                                 }
4250                         }
4251                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4252                 }
4253                 break;
4254         case RENDERPATH_CGGL:
4255 #ifdef SUPPORTCG
4256                 {
4257                         r_cg_permutation_t *p;
4258                         r_cg_permutation = NULL;
4259                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4260                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4261                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4262                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4263                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4264                         for (i = 0;i < limit;i++)
4265                         {
4266                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4267                                 {
4268                                         if (p->vprogram)
4269                                                 cgDestroyProgram(p->vprogram);
4270                                         if (p->fprogram)
4271                                                 cgDestroyProgram(p->fprogram);
4272                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4273                                 }
4274                         }
4275                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4276                 }
4277                 break;
4278 #endif
4279         case RENDERPATH_GL13:
4280         case RENDERPATH_GL11:
4281                 break;
4282         }
4283 }
4284
4285 void R_GLSL_DumpShader_f(void)
4286 {
4287         int i;
4288         qfile_t *file;
4289
4290         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4291         if (file)
4292         {
4293                 FS_Print(file, "/* The engine may define the following macros:\n");
4294                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4295                 for (i = 0;i < SHADERMODE_COUNT;i++)
4296                         FS_Print(file, glslshadermodeinfo[i].pretext);
4297                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4298                         FS_Print(file, shaderpermutationinfo[i].pretext);
4299                 FS_Print(file, "*/\n");
4300                 FS_Print(file, builtinshaderstring);
4301                 FS_Close(file);
4302                 Con_Printf("glsl/default.glsl written\n");
4303         }
4304         else
4305                 Con_Printf("failed to write to glsl/default.glsl\n");
4306
4307 #ifdef SUPPORTCG
4308         file = FS_OpenRealFile("cg/default.cg", "w", false);
4309         if (file)
4310         {
4311                 FS_Print(file, "/* The engine may define the following macros:\n");
4312                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4313                 for (i = 0;i < SHADERMODE_COUNT;i++)
4314                         FS_Print(file, cgshadermodeinfo[i].pretext);
4315                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4316                         FS_Print(file, shaderpermutationinfo[i].pretext);
4317                 FS_Print(file, "*/\n");
4318                 FS_Print(file, builtincgshaderstring);
4319                 FS_Close(file);
4320                 Con_Printf("cg/default.cg written\n");
4321         }
4322         else
4323                 Con_Printf("failed to write to cg/default.cg\n");
4324 #endif
4325 }
4326
4327 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4328 {
4329         if (!second)
4330                 texturemode = GL_MODULATE;
4331         switch (vid.renderpath)
4332         {
4333         case RENDERPATH_GL20:
4334                 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))));
4335                 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
4336                 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, second);
4337                 break;
4338         case RENDERPATH_CGGL:
4339 #ifdef SUPPORTCG
4340                 CHECKCGERROR
4341                 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))));
4342                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4343                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4344 #endif
4345                 break;
4346         case RENDERPATH_GL13:
4347                 R_Mesh_TexBind(0, first );
4348                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4349                 R_Mesh_TexBind(1, second);
4350                 if (second)
4351                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4352                 break;
4353         case RENDERPATH_GL11:
4354                 R_Mesh_TexBind(0, first );
4355                 break;
4356         }
4357 }
4358
4359 void R_SetupShader_DepthOrShadow(void)
4360 {
4361         switch (vid.renderpath)
4362         {
4363         case RENDERPATH_GL20:
4364                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4365                 break;
4366         case RENDERPATH_CGGL:
4367 #ifdef SUPPORTCG
4368                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4369 #endif
4370                 break;
4371         case RENDERPATH_GL13:
4372                 R_Mesh_TexBind(0, 0);
4373                 R_Mesh_TexBind(1, 0);
4374                 break;
4375         case RENDERPATH_GL11:
4376                 R_Mesh_TexBind(0, 0);
4377                 break;
4378         }
4379 }
4380
4381 void R_SetupShader_ShowDepth(void)
4382 {
4383         switch (vid.renderpath)
4384         {
4385         case RENDERPATH_GL20:
4386                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4387                 break;
4388         case RENDERPATH_CGGL:
4389 #ifdef SUPPORTCG
4390                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4391 #endif
4392                 break;
4393         case RENDERPATH_GL13:
4394                 break;
4395         case RENDERPATH_GL11:
4396                 break;
4397         }
4398 }
4399
4400 extern qboolean r_shadow_usingdeferredprepass;
4401 extern cvar_t r_shadow_deferred_8bitrange;
4402 extern rtexture_t *r_shadow_attenuationgradienttexture;
4403 extern rtexture_t *r_shadow_attenuation2dtexture;
4404 extern rtexture_t *r_shadow_attenuation3dtexture;
4405 extern qboolean r_shadow_usingshadowmaprect;
4406 extern qboolean r_shadow_usingshadowmapcube;
4407 extern qboolean r_shadow_usingshadowmap2d;
4408 extern qboolean r_shadow_usingshadowmaportho;
4409 extern float r_shadow_shadowmap_texturescale[2];
4410 extern float r_shadow_shadowmap_parameters[4];
4411 extern qboolean r_shadow_shadowmapvsdct;
4412 extern qboolean r_shadow_shadowmapsampler;
4413 extern int r_shadow_shadowmappcf;
4414 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4415 extern rtexture_t *r_shadow_shadowmap2dtexture;
4416 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4417 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4418 extern matrix4x4_t r_shadow_shadowmapmatrix;
4419 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4420 extern int r_shadow_prepass_width;
4421 extern int r_shadow_prepass_height;
4422 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4423 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4424 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4425 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4426 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
4427 {
4428         // select a permutation of the lighting shader appropriate to this
4429         // combination of texture, entity, light source, and fogging, only use the
4430         // minimum features necessary to avoid wasting rendering time in the
4431         // fragment shader on features that are not being used
4432         unsigned int permutation = 0;
4433         unsigned int mode = 0;
4434         float m16f[16];
4435         if (rsurfacepass == RSURFPASS_BACKGROUND)
4436         {
4437                 // distorted background
4438                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4439                         mode = SHADERMODE_WATER;
4440                 else
4441                         mode = SHADERMODE_REFRACTION;
4442                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4443                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4444                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4445                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4446                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4447                 R_Mesh_ColorPointer(NULL, 0, 0);
4448                 GL_AlphaTest(false);
4449                 GL_BlendFunc(GL_ONE, GL_ZERO);
4450         }
4451         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4452         {
4453                 if (r_glsl_offsetmapping.integer)
4454                 {
4455                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4456                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4457                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4458                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4459                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4460                         {
4461                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4462                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4463                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4464                         }
4465                 }
4466                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4467                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4468                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4469                         permutation |= SHADERPERMUTATION_ALPHAKILL;
4470                 // normalmap (deferred prepass), may use alpha test on diffuse
4471                 mode = SHADERMODE_DEFERREDGEOMETRY;
4472                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4473                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4474                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4475                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4476                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4477                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4478                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4479                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4480                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4481                 else
4482                         R_Mesh_ColorPointer(NULL, 0, 0);
4483                 GL_AlphaTest(false);
4484                 GL_BlendFunc(GL_ONE, GL_ZERO);
4485         }
4486         else if (rsurfacepass == RSURFPASS_RTLIGHT)
4487         {
4488                 if (r_glsl_offsetmapping.integer)
4489                 {
4490                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4491                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4492                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4493                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4494                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4495                         {
4496                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4497                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4498                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4499                         }
4500                 }
4501                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4502                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4503                 // light source
4504                 mode = SHADERMODE_LIGHTSOURCE;
4505                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4506                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4507                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4508                         permutation |= SHADERPERMUTATION_CUBEFILTER;
4509                 if (diffusescale > 0)
4510                         permutation |= SHADERPERMUTATION_DIFFUSE;
4511                 if (specularscale > 0)
4512                 {
4513                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4514                         if (r_shadow_glossexact.integer)
4515                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4516                 }
4517                 if (r_refdef.fogenabled)
4518                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4519                 if (rsurface.texture->colormapping)
4520                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4521                 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4522                 {
4523                         if (r_shadow_usingshadowmaprect)
4524                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4525                         if (r_shadow_usingshadowmap2d)
4526                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4527                         if (r_shadow_usingshadowmapcube)
4528                                 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4529                         else if(r_shadow_shadowmapvsdct)
4530                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4531
4532                         if (r_shadow_shadowmapsampler)
4533                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4534                         if (r_shadow_shadowmappcf > 1)
4535                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4536                         else if (r_shadow_shadowmappcf)
4537                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4538                 }
4539                 if (rsurface.texture->reflectmasktexture)
4540                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4541                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4542                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4543                 {
4544                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4545                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4546                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4547                 }
4548                 else
4549                 {
4550                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4551                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4552                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4553                 }
4554                 //R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4555                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4556                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4557                 else
4558                         R_Mesh_ColorPointer(NULL, 0, 0);
4559                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4560                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4561         }
4562         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4563         {
4564                 if (r_glsl_offsetmapping.integer)
4565                 {
4566                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4567                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4568                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4569                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4570                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4571                         {
4572                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4573                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4574                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4575                         }
4576                 }
4577                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4578                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4579                 // unshaded geometry (fullbright or ambient model lighting)
4580                 mode = SHADERMODE_FLATCOLOR;
4581                 ambientscale = diffusescale = specularscale = 0;
4582                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4583                         permutation |= SHADERPERMUTATION_GLOW;
4584                 if (r_refdef.fogenabled)
4585                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4586                 if (rsurface.texture->colormapping)
4587                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4588                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4589                 {
4590                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4591                         if (r_shadow_usingshadowmaprect)
4592                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4593                         if (r_shadow_usingshadowmap2d)
4594                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4595
4596                         if (r_shadow_shadowmapsampler)
4597                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4598                         if (r_shadow_shadowmappcf > 1)
4599                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4600                         else if (r_shadow_shadowmappcf)
4601                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4602                 }
4603                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4604                         permutation |= SHADERPERMUTATION_REFLECTION;
4605                 if (rsurface.texture->reflectmasktexture)
4606                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4607                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4608                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4609                 {
4610                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4611                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4612                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4613                 }
4614                 else
4615                 {
4616                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4617                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4618                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4619                 }
4620                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4621                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4622                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4623                 else
4624                         R_Mesh_ColorPointer(NULL, 0, 0);
4625                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4626                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4627         }
4628         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4629         {
4630                 if (r_glsl_offsetmapping.integer)
4631                 {
4632                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4633                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4634                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4635                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4636                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4637                         {
4638                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4639                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4640                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4641                         }
4642                 }
4643                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4644                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4645                 // directional model lighting
4646                 mode = SHADERMODE_LIGHTDIRECTION;
4647                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4648                         permutation |= SHADERPERMUTATION_GLOW;
4649                 permutation |= SHADERPERMUTATION_DIFFUSE;
4650                 if (specularscale > 0)
4651                 {
4652                         permutation |= SHADERPERMUTATION_SPECULAR;
4653                         if (r_shadow_glossexact.integer)
4654                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4655                 }
4656                 if (r_refdef.fogenabled)
4657                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4658                 if (rsurface.texture->colormapping)
4659                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4660                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4661                 {
4662                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4663                         if (r_shadow_usingshadowmaprect)
4664                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4665                         if (r_shadow_usingshadowmap2d)
4666                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4667
4668                         if (r_shadow_shadowmapsampler)
4669                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4670                         if (r_shadow_shadowmappcf > 1)
4671                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4672                         else if (r_shadow_shadowmappcf)
4673                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4674                 }
4675                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4676                         permutation |= SHADERPERMUTATION_REFLECTION;
4677                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4678                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4679                 if (rsurface.texture->reflectmasktexture)
4680                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4681                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4682                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4683                 {
4684                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4685                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4686                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4687                 }
4688                 else
4689                 {
4690                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4691                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4692                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4693                 }
4694                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4695                 R_Mesh_ColorPointer(NULL, 0, 0);
4696                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4697                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4698         }
4699         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
4700         {
4701                 if (r_glsl_offsetmapping.integer)
4702                 {
4703                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4704                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4705                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4706                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4707                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4708                         {
4709                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4710                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4711                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4712                         }
4713                 }
4714                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4715                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4716                 // ambient model lighting
4717                 mode = SHADERMODE_LIGHTDIRECTION;
4718                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4719                         permutation |= SHADERPERMUTATION_GLOW;
4720                 if (r_refdef.fogenabled)
4721                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4722                 if (rsurface.texture->colormapping)
4723                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4724                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4725                 {
4726                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4727                         if (r_shadow_usingshadowmaprect)
4728                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4729                         if (r_shadow_usingshadowmap2d)
4730                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4731
4732                         if (r_shadow_shadowmapsampler)
4733                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4734                         if (r_shadow_shadowmappcf > 1)
4735                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4736                         else if (r_shadow_shadowmappcf)
4737                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4738                 }
4739                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4740                         permutation |= SHADERPERMUTATION_REFLECTION;
4741                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4742                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4743                 if (rsurface.texture->reflectmasktexture)
4744                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4745                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4746                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4747                 {
4748                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4749                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4750                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4751                 }
4752                 else
4753                 {
4754                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4755                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4756                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4757                 }
4758                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4759                 R_Mesh_ColorPointer(NULL, 0, 0);
4760                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4761                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4762         }
4763         else
4764         {
4765                 if (r_glsl_offsetmapping.integer)
4766                 {
4767                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4768                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4769                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4770                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4771                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4772                         {
4773                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4774                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4775                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4776                         }
4777                 }
4778                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4779                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4780                 // lightmapped wall
4781                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4782                         permutation |= SHADERPERMUTATION_GLOW;
4783                 if (r_refdef.fogenabled)
4784                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4785                 if (rsurface.texture->colormapping)
4786                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4787                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4788                 {
4789                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4790                         if (r_shadow_usingshadowmaprect)
4791                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4792                         if (r_shadow_usingshadowmap2d)
4793                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4794
4795                         if (r_shadow_shadowmapsampler)
4796                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4797                         if (r_shadow_shadowmappcf > 1)
4798                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4799                         else if (r_shadow_shadowmappcf)
4800                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4801                 }
4802                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4803                         permutation |= SHADERPERMUTATION_REFLECTION;
4804                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4805                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4806                 if (rsurface.texture->reflectmasktexture)
4807                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4808                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
4809                 {
4810                         // deluxemapping (light direction texture)
4811                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
4812                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
4813                         else
4814                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4815                         permutation |= SHADERPERMUTATION_DIFFUSE;
4816                         if (specularscale > 0)
4817                         {
4818                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4819                                 if (r_shadow_glossexact.integer)
4820                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4821                         }
4822                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4823                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4824                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4825                         else
4826                                 R_Mesh_ColorPointer(NULL, 0, 0);
4827                 }
4828                 else if (r_glsl_deluxemapping.integer >= 2)
4829                 {
4830                         // fake deluxemapping (uniform light direction in tangentspace)
4831                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4832                         permutation |= SHADERPERMUTATION_DIFFUSE;
4833                         if (specularscale > 0)
4834                         {
4835                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4836                                 if (r_shadow_glossexact.integer)
4837                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4838                         }
4839                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4840                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4841                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4842                         else
4843                                 R_Mesh_ColorPointer(NULL, 0, 0);
4844                 }
4845                 else if (rsurface.uselightmaptexture)
4846                 {
4847                         // ordinary lightmapping (q1bsp, q3bsp)
4848                         mode = SHADERMODE_LIGHTMAP;
4849                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4850                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4851                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4852                         else
4853                                 R_Mesh_ColorPointer(NULL, 0, 0);
4854                 }
4855                 else
4856                 {
4857                         // ordinary vertex coloring (q3bsp)
4858                         mode = SHADERMODE_VERTEXCOLOR;
4859                         R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4860                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4861                 }
4862                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4863                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4864                 {
4865                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4866                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4867                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4868                 }
4869                 else
4870                 {
4871                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4872                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4873                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4874                 }
4875                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4876                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4877         }
4878         switch(vid.renderpath)
4879         {
4880         case RENDERPATH_GL20:
4881                 R_SetupShader_SetPermutationGLSL(mode, permutation);
4882                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
4883                 if (mode == SHADERMODE_LIGHTSOURCE)
4884                 {
4885                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
4886                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
4887                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
4888                         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);
4889                         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);
4890                         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);
4891         
4892                         // additive passes are only darkened by fog, not tinted
4893                         if (r_glsl_permutation->loc_FogColor >= 0)
4894                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4895                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4896                 }
4897                 else
4898                 {
4899                         if (mode == SHADERMODE_FLATCOLOR)
4900                         {
4901                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
4902                         }
4903                         else if (mode == SHADERMODE_LIGHTDIRECTION)
4904                         {
4905                                 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]);
4906                                 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]);
4907                                 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);
4908                                 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);
4909                                 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);
4910                                 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]);
4911                                 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]);
4912                         }
4913                         else
4914                         {
4915                                 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]);
4916                                 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]);
4917                                 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);
4918                                 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);
4919                                 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);
4920                         }
4921                         // additive passes are only darkened by fog, not tinted
4922                         if (r_glsl_permutation->loc_FogColor >= 0)
4923                         {
4924                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4925                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4926                                 else
4927                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4928                         }
4929                         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);
4930                         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]);
4931                         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]);
4932                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
4933                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
4934                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
4935                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
4936                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4937                 }
4938                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
4939                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
4940                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
4941                 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]);
4942                 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]);
4943
4944                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
4945                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
4946                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
4947                 if (r_glsl_permutation->loc_Color_Pants >= 0)
4948                 {
4949                         if (rsurface.texture->pantstexture)
4950                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4951                         else
4952                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
4953                 }
4954                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
4955                 {
4956                         if (rsurface.texture->shirttexture)
4957                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4958                         else
4959                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
4960                 }
4961                 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]);
4962                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
4963                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
4964                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
4965                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
4966                 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]);
4967                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
4968
4969         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
4970         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
4971         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
4972                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
4973                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
4974                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
4975                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
4976                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
4977                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
4978                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
4979                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
4980                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
4981                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
4982                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
4983                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
4984                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
4985                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_white                                     );
4986                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_blanknormalmap                            );
4987                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
4988                 if (r_glsl_permutation->loc_Texture_Refraction      >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , r_texture_white                                     );
4989                 if (r_glsl_permutation->loc_Texture_Reflection      >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , r_texture_white                                     );
4990                 if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
4991                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
4992                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
4993                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
4994                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
4995                 {
4996                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
4997                         if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT, r_shadow_shadowmaprectangletexture                  );
4998                         if (rsurface.rtlight)
4999                         {
5000                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5001                                 if (r_shadow_usingshadowmapcube)
5002                                         if (r_glsl_permutation->loc_Texture_ShadowMapCube   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE     , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5003                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5004                         }
5005                 }
5006                 CHECKGLERROR
5007                 break;
5008         case RENDERPATH_CGGL:
5009 #ifdef SUPPORTCG
5010                 R_SetupShader_SetPermutationCG(mode, permutation);
5011                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
5012                 if (mode == SHADERMODE_LIGHTSOURCE)
5013                 {
5014                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
5015                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5016                 }
5017                 else
5018                 {
5019                         if (mode == SHADERMODE_LIGHTDIRECTION)
5020                         {
5021                                 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
5022                         }
5023                 }
5024                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
5025                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
5026                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
5027                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5028                 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
5029                 CHECKGLERROR
5030
5031                 if (mode == SHADERMODE_LIGHTSOURCE)
5032                 {
5033                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5034                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
5035                         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
5036                         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
5037                         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
5038
5039                         // additive passes are only darkened by fog, not tinted
5040                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
5041                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5042                 }
5043                 else
5044                 {
5045                         if (mode == SHADERMODE_FLATCOLOR)
5046                         {
5047                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);CHECKCGERROR
5048                         }
5049                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5050                         {
5051                                 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
5052                                 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
5053                                 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
5054                                 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
5055                                 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
5056                                 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
5057                                 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
5058                         }
5059                         else
5060                         {
5061                                 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
5062                                 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
5063                                 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
5064                                 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
5065                                 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
5066                         }
5067                         // additive passes are only darkened by fog, not tinted
5068                         if (r_cg_permutation->fp_FogColor)
5069                         {
5070                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5071                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
5072                                 else
5073                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5074                                 CHECKCGERROR
5075                         }
5076                         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
5077                         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
5078                         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
5079                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
5080                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
5081                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
5082                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
5083                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5084                 }
5085                 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
5086                 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
5087                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
5088                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
5089                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5090                 if (r_cg_permutation->fp_Color_Pants)
5091                 {
5092                         if (rsurface.texture->pantstexture)
5093                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5094                         else
5095                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
5096                         CHECKCGERROR
5097                 }
5098                 if (r_cg_permutation->fp_Color_Shirt)
5099                 {
5100                         if (rsurface.texture->shirttexture)
5101                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5102                         else
5103                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
5104                         CHECKCGERROR
5105                 }
5106                 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
5107                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
5108                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
5109                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
5110                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
5111                 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
5112                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5113
5114         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
5115         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
5116         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
5117                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
5118                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
5119                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
5120                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
5121                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
5122                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
5123                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
5124                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
5125                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
5126                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
5127                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
5128                 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
5129                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
5130                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , r_texture_white                                     );CHECKCGERROR
5131                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , r_texture_blanknormalmap                            );CHECKCGERROR
5132                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
5133                 if (r_cg_permutation->fp_Texture_Refraction     ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction     , r_texture_white                                     );CHECKCGERROR
5134                 if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , r_texture_white                                     );CHECKCGERROR
5135                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
5136                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
5137                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
5138                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
5139                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5140                 {
5141                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5142                         if (r_cg_permutation->fp_Texture_ShadowMapRect  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
5143                         if (rsurface.rtlight)
5144                         {
5145                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
5146                                 if (r_shadow_usingshadowmapcube)
5147                                         if (r_cg_permutation->fp_Texture_ShadowMapCube  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5148                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
5149                         }
5150                 }
5151
5152                 CHECKGLERROR
5153 #endif
5154                 break;
5155         case RENDERPATH_GL13:
5156         case RENDERPATH_GL11:
5157                 break;
5158         }
5159 }
5160
5161 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
5162 {
5163         // select a permutation of the lighting shader appropriate to this
5164         // combination of texture, entity, light source, and fogging, only use the
5165         // minimum features necessary to avoid wasting rendering time in the
5166         // fragment shader on features that are not being used
5167         unsigned int permutation = 0;
5168         unsigned int mode = 0;
5169         const float *lightcolorbase = rtlight->currentcolor;
5170         float ambientscale = rtlight->ambientscale;
5171         float diffusescale = rtlight->diffusescale;
5172         float specularscale = rtlight->specularscale;
5173         // this is the location of the light in view space
5174         vec3_t viewlightorigin;
5175         // this transforms from view space (camera) to light space (cubemap)
5176         matrix4x4_t viewtolight;
5177         matrix4x4_t lighttoview;
5178         float viewtolight16f[16];
5179         float range = 1.0f / r_shadow_deferred_8bitrange.value;
5180         // light source
5181         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
5182         if (rtlight->currentcubemap != r_texture_whitecube)
5183                 permutation |= SHADERPERMUTATION_CUBEFILTER;
5184         if (diffusescale > 0)
5185                 permutation |= SHADERPERMUTATION_DIFFUSE;
5186         if (specularscale > 0)
5187         {
5188                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5189                 if (r_shadow_glossexact.integer)
5190                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5191         }
5192         if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
5193         {
5194                 if (r_shadow_usingshadowmaprect)
5195                         permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5196                 if (r_shadow_usingshadowmap2d)
5197                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5198                 if (r_shadow_usingshadowmapcube)
5199                         permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
5200                 else if(r_shadow_shadowmapvsdct)
5201                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5202
5203                 if (r_shadow_shadowmapsampler)
5204                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5205                 if (r_shadow_shadowmappcf > 1)
5206                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5207                 else if (r_shadow_shadowmappcf)
5208                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5209         }
5210         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
5211         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
5212         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
5213         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
5214         switch(vid.renderpath)
5215         {
5216         case RENDERPATH_GL20:
5217                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5218                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5219                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
5220                 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);
5221                 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);
5222                 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);
5223                 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]);
5224                 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]);
5225                 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));
5226                 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]);
5227                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5228
5229                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
5230                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
5231                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
5232                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
5233                 if (r_glsl_permutation->loc_Texture_ShadowMapRect     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT      , r_shadow_shadowmaprectangletexture                  );
5234                 if (r_shadow_usingshadowmapcube)
5235                         if (r_glsl_permutation->loc_Texture_ShadowMapCube     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE      , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5236                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
5237                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
5238                 break;
5239         case RENDERPATH_CGGL:
5240 #ifdef SUPPORTCG
5241                 R_SetupShader_SetPermutationCG(mode, permutation);
5242                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
5243                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
5244                 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
5245                 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
5246                 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
5247                 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
5248                 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
5249                 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
5250                 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
5251                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5252
5253                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
5254                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
5255                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
5256                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
5257                 if (r_cg_permutation->fp_Texture_ShadowMapRect    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
5258                 if (r_shadow_usingshadowmapcube)
5259                         if (r_cg_permutation->fp_Texture_ShadowMapCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5260                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5261                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
5262 #endif
5263                 break;
5264         case RENDERPATH_GL13:
5265         case RENDERPATH_GL11:
5266                 break;
5267         }
5268 }
5269
5270 #define SKINFRAME_HASH 1024
5271
5272 typedef struct
5273 {
5274         int loadsequence; // incremented each level change
5275         memexpandablearray_t array;
5276         skinframe_t *hash[SKINFRAME_HASH];
5277 }
5278 r_skinframe_t;
5279 r_skinframe_t r_skinframe;
5280
5281 void R_SkinFrame_PrepareForPurge(void)
5282 {
5283         r_skinframe.loadsequence++;
5284         // wrap it without hitting zero
5285         if (r_skinframe.loadsequence >= 200)
5286                 r_skinframe.loadsequence = 1;
5287 }
5288
5289 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5290 {
5291         if (!skinframe)
5292                 return;
5293         // mark the skinframe as used for the purging code
5294         skinframe->loadsequence = r_skinframe.loadsequence;
5295 }
5296
5297 void R_SkinFrame_Purge(void)
5298 {
5299         int i;
5300         skinframe_t *s;
5301         for (i = 0;i < SKINFRAME_HASH;i++)
5302         {
5303                 for (s = r_skinframe.hash[i];s;s = s->next)
5304                 {
5305                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5306                         {
5307                                 if (s->merged == s->base)
5308                                         s->merged = NULL;
5309                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5310                                 R_PurgeTexture(s->stain );s->stain  = NULL;
5311                                 R_PurgeTexture(s->merged);s->merged = NULL;
5312                                 R_PurgeTexture(s->base  );s->base   = NULL;
5313                                 R_PurgeTexture(s->pants );s->pants  = NULL;
5314                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
5315                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
5316                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
5317                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
5318                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
5319                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
5320                                 s->loadsequence = 0;
5321                         }
5322                 }
5323         }
5324 }
5325
5326 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5327         skinframe_t *item;
5328         char basename[MAX_QPATH];
5329
5330         Image_StripImageExtension(name, basename, sizeof(basename));
5331
5332         if( last == NULL ) {
5333                 int hashindex;
5334                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5335                 item = r_skinframe.hash[hashindex];
5336         } else {
5337                 item = last->next;
5338         }
5339
5340         // linearly search through the hash bucket
5341         for( ; item ; item = item->next ) {
5342                 if( !strcmp( item->basename, basename ) ) {
5343                         return item;
5344                 }
5345         }
5346         return NULL;
5347 }
5348
5349 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5350 {
5351         skinframe_t *item;
5352         int hashindex;
5353         char basename[MAX_QPATH];
5354
5355         Image_StripImageExtension(name, basename, sizeof(basename));
5356
5357         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5358         for (item = r_skinframe.hash[hashindex];item;item = item->next)
5359                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5360                         break;
5361
5362         if (!item) {
5363                 rtexture_t *dyntexture;
5364                 // check whether its a dynamic texture
5365                 dyntexture = CL_GetDynTexture( basename );
5366                 if (!add && !dyntexture)
5367                         return NULL;
5368                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5369                 memset(item, 0, sizeof(*item));
5370                 strlcpy(item->basename, basename, sizeof(item->basename));
5371                 item->base = dyntexture; // either NULL or dyntexture handle
5372                 item->textureflags = textureflags;
5373                 item->comparewidth = comparewidth;
5374                 item->compareheight = compareheight;
5375                 item->comparecrc = comparecrc;
5376                 item->next = r_skinframe.hash[hashindex];
5377                 r_skinframe.hash[hashindex] = item;
5378         }
5379         else if( item->base == NULL )
5380         {
5381                 rtexture_t *dyntexture;
5382                 // check whether its a dynamic texture
5383                 // 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]
5384                 dyntexture = CL_GetDynTexture( basename );
5385                 item->base = dyntexture; // either NULL or dyntexture handle
5386         }
5387
5388         R_SkinFrame_MarkUsed(item);
5389         return item;
5390 }
5391
5392 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5393         { \
5394                 unsigned long long avgcolor[5], wsum; \
5395                 int pix, comp, w; \
5396                 avgcolor[0] = 0; \
5397                 avgcolor[1] = 0; \
5398                 avgcolor[2] = 0; \
5399                 avgcolor[3] = 0; \
5400                 avgcolor[4] = 0; \
5401                 wsum = 0; \
5402                 for(pix = 0; pix < cnt; ++pix) \
5403                 { \
5404                         w = 0; \
5405                         for(comp = 0; comp < 3; ++comp) \
5406                                 w += getpixel; \
5407                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5408                         { \
5409                                 ++wsum; \
5410                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5411                                 w = getpixel; \
5412                                 for(comp = 0; comp < 3; ++comp) \
5413                                         avgcolor[comp] += getpixel * w; \
5414                                 avgcolor[3] += w; \
5415                         } \
5416                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5417                         avgcolor[4] += getpixel; \
5418                 } \
5419                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5420                         avgcolor[3] = 1; \
5421                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5422                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5423                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5424                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5425         }
5426
5427 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5428 {
5429         int j;
5430         unsigned char *pixels;
5431         unsigned char *bumppixels;
5432         unsigned char *basepixels = NULL;
5433         int basepixels_width = 0;
5434         int basepixels_height = 0;
5435         skinframe_t *skinframe;
5436         rtexture_t *ddsbase = NULL;
5437         qboolean ddshasalpha = false;
5438         float ddsavgcolor[4];
5439         char basename[MAX_QPATH];
5440
5441         if (cls.state == ca_dedicated)
5442                 return NULL;
5443
5444         // return an existing skinframe if already loaded
5445         // if loading of the first image fails, don't make a new skinframe as it
5446         // would cause all future lookups of this to be missing
5447         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5448         if (skinframe && skinframe->base)
5449                 return skinframe;
5450
5451         Image_StripImageExtension(name, basename, sizeof(basename));
5452
5453         // check for DDS texture file first
5454         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor)))
5455         {
5456                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer);
5457                 if (basepixels == NULL)
5458                         return NULL;
5459         }
5460
5461         if (developer_loading.integer)
5462                 Con_Printf("loading skin \"%s\"\n", name);
5463
5464         // we've got some pixels to store, so really allocate this new texture now
5465         if (!skinframe)
5466                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5467         skinframe->stain = NULL;
5468         skinframe->merged = NULL;
5469         skinframe->base = NULL;
5470         skinframe->pants = NULL;
5471         skinframe->shirt = NULL;
5472         skinframe->nmap = NULL;
5473         skinframe->gloss = NULL;
5474         skinframe->glow = NULL;
5475         skinframe->fog = NULL;
5476         skinframe->reflect = NULL;
5477         skinframe->hasalpha = false;
5478
5479         if (ddsbase)
5480         {
5481                 skinframe->base = ddsbase;
5482                 skinframe->hasalpha = ddshasalpha;
5483                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5484                 if (r_loadfog && skinframe->hasalpha)
5485                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5486                 //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]);
5487         }
5488         else
5489         {
5490                 basepixels_width = image_width;
5491                 basepixels_height = image_height;
5492                 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);
5493                 if (textureflags & TEXF_ALPHA)
5494                 {
5495                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5496                         {
5497                                 if (basepixels[j] < 255)
5498                                 {
5499                                         skinframe->hasalpha = true;
5500                                         break;
5501                                 }
5502                         }
5503                         if (r_loadfog && skinframe->hasalpha)
5504                         {
5505                                 // has transparent pixels
5506                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5507                                 for (j = 0;j < image_width * image_height * 4;j += 4)
5508                                 {
5509                                         pixels[j+0] = 255;
5510                                         pixels[j+1] = 255;
5511                                         pixels[j+2] = 255;
5512                                         pixels[j+3] = basepixels[j+3];
5513                                 }
5514                                 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);
5515                                 Mem_Free(pixels);
5516                         }
5517                 }
5518                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5519                 //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]);
5520                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5521                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true);
5522                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
5523                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true);
5524         }
5525
5526         if (r_loaddds)
5527         {
5528                 if (r_loadnormalmap)
5529                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5530                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL);
5531                 if (r_loadgloss)
5532                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL);
5533                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL);
5534                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL);
5535                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL);
5536         }
5537
5538         // _norm is the name used by tenebrae and has been adopted as standard
5539         if (r_loadnormalmap && skinframe->nmap == NULL)
5540         {
5541                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false)) != NULL)
5542                 {
5543                         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);
5544                         Mem_Free(pixels);
5545                         pixels = NULL;
5546                 }
5547                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false)) != NULL)
5548                 {
5549                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5550                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5551                         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);
5552                         Mem_Free(pixels);
5553                         Mem_Free(bumppixels);
5554                 }
5555                 else if (r_shadow_bumpscale_basetexture.value > 0)
5556                 {
5557                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5558                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5559                         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);
5560                         Mem_Free(pixels);
5561                 }
5562                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
5563                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true);
5564         }
5565
5566         // _luma is supported only for tenebrae compatibility
5567         // _glow is the preferred name
5568         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))))
5569         {
5570                 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);
5571                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
5572                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true);
5573                 Mem_Free(pixels);pixels = NULL;
5574         }
5575
5576         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5577         {
5578                 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);
5579                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
5580                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true);
5581                 Mem_Free(pixels);
5582                 pixels = NULL;
5583         }
5584
5585         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5586         {
5587                 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);
5588                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
5589                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true);
5590                 Mem_Free(pixels);
5591                 pixels = NULL;
5592         }
5593
5594         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5595         {
5596                 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);
5597                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
5598                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true);
5599                 Mem_Free(pixels);
5600                 pixels = NULL;
5601         }
5602
5603         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5604         {
5605                 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);
5606                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
5607                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true);
5608                 Mem_Free(pixels);
5609                 pixels = NULL;
5610         }
5611
5612         if (basepixels)
5613                 Mem_Free(basepixels);
5614
5615         return skinframe;
5616 }
5617
5618 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
5619 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
5620 {
5621         int i;
5622         unsigned char *temp1, *temp2;
5623         skinframe_t *skinframe;
5624
5625         if (cls.state == ca_dedicated)
5626                 return NULL;
5627
5628         // if already loaded just return it, otherwise make a new skinframe
5629         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
5630         if (skinframe && skinframe->base)
5631                 return skinframe;
5632
5633         skinframe->stain = NULL;
5634         skinframe->merged = NULL;
5635         skinframe->base = NULL;
5636         skinframe->pants = NULL;
5637         skinframe->shirt = NULL;
5638         skinframe->nmap = NULL;
5639         skinframe->gloss = NULL;
5640         skinframe->glow = NULL;
5641         skinframe->fog = NULL;
5642         skinframe->reflect = NULL;
5643         skinframe->hasalpha = false;
5644
5645         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5646         if (!skindata)
5647                 return NULL;
5648
5649         if (developer_loading.integer)
5650                 Con_Printf("loading 32bit skin \"%s\"\n", name);
5651
5652         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
5653         {
5654                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5655                 temp2 = temp1 + width * height * 4;
5656                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5657                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5658                 Mem_Free(temp1);
5659         }
5660         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5661         if (textureflags & TEXF_ALPHA)
5662         {
5663                 for (i = 3;i < width * height * 4;i += 4)
5664                 {
5665                         if (skindata[i] < 255)
5666                         {
5667                                 skinframe->hasalpha = true;
5668                                 break;
5669                         }
5670                 }
5671                 if (r_loadfog && skinframe->hasalpha)
5672                 {
5673                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
5674                         memcpy(fogpixels, skindata, width * height * 4);
5675                         for (i = 0;i < width * height * 4;i += 4)
5676                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
5677                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5678                         Mem_Free(fogpixels);
5679                 }
5680         }
5681
5682         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
5683         //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]);
5684
5685         return skinframe;
5686 }
5687
5688 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
5689 {
5690         int i;
5691         int featuresmask;
5692         skinframe_t *skinframe;
5693
5694         if (cls.state == ca_dedicated)
5695                 return NULL;
5696
5697         // if already loaded just return it, otherwise make a new skinframe
5698         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5699         if (skinframe && skinframe->base)
5700                 return skinframe;
5701
5702         skinframe->stain = NULL;
5703         skinframe->merged = NULL;
5704         skinframe->base = NULL;
5705         skinframe->pants = NULL;
5706         skinframe->shirt = NULL;
5707         skinframe->nmap = NULL;
5708         skinframe->gloss = NULL;
5709         skinframe->glow = NULL;
5710         skinframe->fog = NULL;
5711         skinframe->reflect = NULL;
5712         skinframe->hasalpha = false;
5713
5714         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5715         if (!skindata)
5716                 return NULL;
5717
5718         if (developer_loading.integer)
5719                 Con_Printf("loading quake skin \"%s\"\n", name);
5720
5721         // 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)
5722         skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
5723         memcpy(skinframe->qpixels, skindata, width*height);
5724         skinframe->qwidth = width;
5725         skinframe->qheight = height;
5726
5727         featuresmask = 0;
5728         for (i = 0;i < width * height;i++)
5729                 featuresmask |= palette_featureflags[skindata[i]];
5730
5731         skinframe->hasalpha = false;
5732         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
5733         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
5734         skinframe->qgeneratemerged = true;
5735         skinframe->qgeneratebase = skinframe->qhascolormapping;
5736         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
5737
5738         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
5739         //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]);
5740
5741         return skinframe;
5742 }
5743
5744 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
5745 {
5746         int width;
5747         int height;
5748         unsigned char *skindata;
5749
5750         if (!skinframe->qpixels)
5751                 return;
5752
5753         if (!skinframe->qhascolormapping)
5754                 colormapped = false;
5755
5756         if (colormapped)
5757         {
5758                 if (!skinframe->qgeneratebase)
5759                         return;
5760         }
5761         else
5762         {
5763                 if (!skinframe->qgeneratemerged)
5764                         return;
5765         }
5766
5767         width = skinframe->qwidth;
5768         height = skinframe->qheight;
5769         skindata = skinframe->qpixels;
5770
5771         if (skinframe->qgeneratenmap)
5772         {
5773                 unsigned char *temp1, *temp2;
5774                 skinframe->qgeneratenmap = false;
5775                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5776                 temp2 = temp1 + width * height * 4;
5777                 // use either a custom palette or the quake palette
5778                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
5779                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5780                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5781                 Mem_Free(temp1);
5782         }
5783
5784         if (skinframe->qgenerateglow)
5785         {
5786                 skinframe->qgenerateglow = false;
5787                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
5788         }
5789
5790         if (colormapped)
5791         {
5792                 skinframe->qgeneratebase = false;
5793                 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);
5794                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
5795                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
5796         }
5797         else
5798         {
5799                 skinframe->qgeneratemerged = false;
5800                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
5801         }
5802
5803         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
5804         {
5805                 Mem_Free(skinframe->qpixels);
5806                 skinframe->qpixels = NULL;
5807         }
5808 }
5809
5810 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)
5811 {
5812         int i;
5813         skinframe_t *skinframe;
5814
5815         if (cls.state == ca_dedicated)
5816                 return NULL;
5817
5818         // if already loaded just return it, otherwise make a new skinframe
5819         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5820         if (skinframe && skinframe->base)
5821                 return skinframe;
5822
5823         skinframe->stain = NULL;
5824         skinframe->merged = NULL;
5825         skinframe->base = NULL;
5826         skinframe->pants = NULL;
5827         skinframe->shirt = NULL;
5828         skinframe->nmap = NULL;
5829         skinframe->gloss = NULL;
5830         skinframe->glow = NULL;
5831         skinframe->fog = NULL;
5832         skinframe->reflect = NULL;
5833         skinframe->hasalpha = false;
5834
5835         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5836         if (!skindata)
5837                 return NULL;
5838
5839         if (developer_loading.integer)
5840                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
5841
5842         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
5843         if (textureflags & TEXF_ALPHA)
5844         {
5845                 for (i = 0;i < width * height;i++)
5846                 {
5847                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
5848                         {
5849                                 skinframe->hasalpha = true;
5850                                 break;
5851                         }
5852                 }
5853                 if (r_loadfog && skinframe->hasalpha)
5854                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
5855         }
5856
5857         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
5858         //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]);
5859
5860         return skinframe;
5861 }
5862
5863 skinframe_t *R_SkinFrame_LoadMissing(void)
5864 {
5865         skinframe_t *skinframe;
5866
5867         if (cls.state == ca_dedicated)
5868                 return NULL;
5869
5870         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
5871         skinframe->stain = NULL;
5872         skinframe->merged = NULL;
5873         skinframe->base = NULL;
5874         skinframe->pants = NULL;
5875         skinframe->shirt = NULL;
5876         skinframe->nmap = NULL;
5877         skinframe->gloss = NULL;
5878         skinframe->glow = NULL;
5879         skinframe->fog = NULL;
5880         skinframe->reflect = NULL;
5881         skinframe->hasalpha = false;
5882
5883         skinframe->avgcolor[0] = rand() / RAND_MAX;
5884         skinframe->avgcolor[1] = rand() / RAND_MAX;
5885         skinframe->avgcolor[2] = rand() / RAND_MAX;
5886         skinframe->avgcolor[3] = 1;
5887
5888         return skinframe;
5889 }
5890
5891 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
5892 typedef struct suffixinfo_s
5893 {
5894         char *suffix;
5895         qboolean flipx, flipy, flipdiagonal;
5896 }
5897 suffixinfo_t;
5898 static suffixinfo_t suffix[3][6] =
5899 {
5900         {
5901                 {"px",   false, false, false},
5902                 {"nx",   false, false, false},
5903                 {"py",   false, false, false},
5904                 {"ny",   false, false, false},
5905                 {"pz",   false, false, false},
5906                 {"nz",   false, false, false}
5907         },
5908         {
5909                 {"posx", false, false, false},
5910                 {"negx", false, false, false},
5911                 {"posy", false, false, false},
5912                 {"negy", false, false, false},
5913                 {"posz", false, false, false},
5914                 {"negz", false, false, false}
5915         },
5916         {
5917                 {"rt",    true, false,  true},
5918                 {"lf",   false,  true,  true},
5919                 {"ft",    true,  true, false},
5920                 {"bk",   false, false, false},
5921                 {"up",    true, false,  true},
5922                 {"dn",    true, false,  true}
5923         }
5924 };
5925
5926 static int componentorder[4] = {0, 1, 2, 3};
5927
5928 rtexture_t *R_LoadCubemap(const char *basename)
5929 {
5930         int i, j, cubemapsize;
5931         unsigned char *cubemappixels, *image_buffer;
5932         rtexture_t *cubemaptexture;
5933         char name[256];
5934         // must start 0 so the first loadimagepixels has no requested width/height
5935         cubemapsize = 0;
5936         cubemappixels = NULL;
5937         cubemaptexture = NULL;
5938         // keep trying different suffix groups (posx, px, rt) until one loads
5939         for (j = 0;j < 3 && !cubemappixels;j++)
5940         {
5941                 // load the 6 images in the suffix group
5942                 for (i = 0;i < 6;i++)
5943                 {
5944                         // generate an image name based on the base and and suffix
5945                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
5946                         // load it
5947                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer)))
5948                         {
5949                                 // an image loaded, make sure width and height are equal
5950                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
5951                                 {
5952                                         // if this is the first image to load successfully, allocate the cubemap memory
5953                                         if (!cubemappixels && image_width >= 1)
5954                                         {
5955                                                 cubemapsize = image_width;
5956                                                 // note this clears to black, so unavailable sides are black
5957                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
5958                                         }
5959                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
5960                                         if (cubemappixels)
5961                                                 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);
5962                                 }
5963                                 else
5964                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
5965                                 // free the image
5966                                 Mem_Free(image_buffer);
5967                         }
5968                 }
5969         }
5970         // if a cubemap loaded, upload it
5971         if (cubemappixels)
5972         {
5973                 if (developer_loading.integer)
5974                         Con_Printf("loading cubemap \"%s\"\n", basename);
5975
5976                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR, NULL);
5977                 Mem_Free(cubemappixels);
5978         }
5979         else
5980         {
5981                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
5982                 if (developer_loading.integer)
5983                 {
5984                         Con_Printf("(tried tried images ");
5985                         for (j = 0;j < 3;j++)
5986                                 for (i = 0;i < 6;i++)
5987                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
5988                         Con_Print(" and was unable to find any of them).\n");
5989                 }
5990         }
5991         return cubemaptexture;
5992 }
5993
5994 rtexture_t *R_GetCubemap(const char *basename)
5995 {
5996         int i;
5997         for (i = 0;i < r_texture_numcubemaps;i++)
5998                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
5999                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6000         if (i >= MAX_CUBEMAPS)
6001                 return r_texture_whitecube;
6002         r_texture_numcubemaps++;
6003         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6004         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6005         return r_texture_cubemaps[i].texture;
6006 }
6007
6008 void R_FreeCubemaps(void)
6009 {
6010         int i;
6011         for (i = 0;i < r_texture_numcubemaps;i++)
6012         {
6013                 if (developer_loading.integer)
6014                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6015                 if (r_texture_cubemaps[i].texture)
6016                         R_FreeTexture(r_texture_cubemaps[i].texture);
6017         }
6018         r_texture_numcubemaps = 0;
6019 }
6020
6021 void R_Main_FreeViewCache(void)
6022 {
6023         if (r_refdef.viewcache.entityvisible)
6024                 Mem_Free(r_refdef.viewcache.entityvisible);
6025         if (r_refdef.viewcache.world_pvsbits)
6026                 Mem_Free(r_refdef.viewcache.world_pvsbits);
6027         if (r_refdef.viewcache.world_leafvisible)
6028                 Mem_Free(r_refdef.viewcache.world_leafvisible);
6029         if (r_refdef.viewcache.world_surfacevisible)
6030                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6031         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6032 }
6033
6034 void R_Main_ResizeViewCache(void)
6035 {
6036         int numentities = r_refdef.scene.numentities;
6037         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6038         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6039         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6040         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6041         if (r_refdef.viewcache.maxentities < numentities)
6042         {
6043                 r_refdef.viewcache.maxentities = numentities;
6044                 if (r_refdef.viewcache.entityvisible)
6045                         Mem_Free(r_refdef.viewcache.entityvisible);
6046                 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6047         }
6048         if (r_refdef.viewcache.world_numclusters != numclusters)
6049         {
6050                 r_refdef.viewcache.world_numclusters = numclusters;
6051                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6052                 if (r_refdef.viewcache.world_pvsbits)
6053                         Mem_Free(r_refdef.viewcache.world_pvsbits);
6054                 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6055         }
6056         if (r_refdef.viewcache.world_numleafs != numleafs)
6057         {
6058                 r_refdef.viewcache.world_numleafs = numleafs;
6059                 if (r_refdef.viewcache.world_leafvisible)
6060                         Mem_Free(r_refdef.viewcache.world_leafvisible);
6061                 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6062         }
6063         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6064         {
6065                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6066                 if (r_refdef.viewcache.world_surfacevisible)
6067                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
6068                 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6069         }
6070 }
6071
6072 extern rtexture_t *loadingscreentexture;
6073 void gl_main_start(void)
6074 {
6075         loadingscreentexture = NULL;
6076         r_texture_blanknormalmap = NULL;
6077         r_texture_white = NULL;
6078         r_texture_grey128 = NULL;
6079         r_texture_black = NULL;
6080         r_texture_whitecube = NULL;
6081         r_texture_normalizationcube = NULL;
6082         r_texture_fogattenuation = NULL;
6083         r_texture_gammaramps = NULL;
6084         r_texture_numcubemaps = 0;
6085
6086         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
6087         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6088
6089         switch(vid.renderpath)
6090         {
6091         case RENDERPATH_GL20:
6092         case RENDERPATH_CGGL:
6093                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6094                 Cvar_SetValueQuick(&gl_combine, 1);
6095                 Cvar_SetValueQuick(&r_glsl, 1);
6096                 r_loadnormalmap = true;
6097                 r_loadgloss = true;
6098                 r_loadfog = false;
6099                 break;
6100         case RENDERPATH_GL13:
6101                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6102                 Cvar_SetValueQuick(&gl_combine, 1);
6103                 Cvar_SetValueQuick(&r_glsl, 0);
6104                 r_loadnormalmap = false;
6105                 r_loadgloss = false;
6106                 r_loadfog = true;
6107                 break;
6108         case RENDERPATH_GL11:
6109                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6110                 Cvar_SetValueQuick(&gl_combine, 0);
6111                 Cvar_SetValueQuick(&r_glsl, 0);
6112                 r_loadnormalmap = false;
6113                 r_loadgloss = false;
6114                 r_loadfog = true;
6115                 break;
6116         }
6117
6118         R_AnimCache_Free();
6119         R_FrameData_Reset();
6120
6121         r_numqueries = 0;
6122         r_maxqueries = 0;
6123         memset(r_queries, 0, sizeof(r_queries));
6124
6125         r_qwskincache = NULL;
6126         r_qwskincache_size = 0;
6127
6128         // set up r_skinframe loading system for textures
6129         memset(&r_skinframe, 0, sizeof(r_skinframe));
6130         r_skinframe.loadsequence = 1;
6131         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
6132
6133         r_main_texturepool = R_AllocTexturePool();
6134         R_BuildBlankTextures();
6135         R_BuildNoTexture();
6136         if (vid.support.arb_texture_cube_map)
6137         {
6138                 R_BuildWhiteCube();
6139                 R_BuildNormalizationCube();
6140         }
6141         r_texture_fogattenuation = NULL;
6142         r_texture_gammaramps = NULL;
6143         //r_texture_fogintensity = NULL;
6144         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6145         memset(&r_waterstate, 0, sizeof(r_waterstate));
6146         r_glsl_permutation = NULL;
6147         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6148         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
6149         glslshaderstring = NULL;
6150 #ifdef SUPPORTCG
6151         r_cg_permutation = NULL;
6152         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
6153         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
6154         cgshaderstring = NULL;
6155 #endif
6156         memset(&r_svbsp, 0, sizeof (r_svbsp));
6157
6158         r_refdef.fogmasktable_density = 0;
6159 }
6160
6161 void gl_main_shutdown(void)
6162 {
6163         R_AnimCache_Free();
6164         R_FrameData_Reset();
6165
6166         R_Main_FreeViewCache();
6167
6168         if (r_maxqueries)
6169                 qglDeleteQueriesARB(r_maxqueries, r_queries);
6170
6171         r_numqueries = 0;
6172         r_maxqueries = 0;
6173         memset(r_queries, 0, sizeof(r_queries));
6174
6175         r_qwskincache = NULL;
6176         r_qwskincache_size = 0;
6177
6178         // clear out the r_skinframe state
6179         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
6180         memset(&r_skinframe, 0, sizeof(r_skinframe));
6181
6182         if (r_svbsp.nodes)
6183                 Mem_Free(r_svbsp.nodes);
6184         memset(&r_svbsp, 0, sizeof (r_svbsp));
6185         R_FreeTexturePool(&r_main_texturepool);
6186         loadingscreentexture = NULL;
6187         r_texture_blanknormalmap = NULL;
6188         r_texture_white = NULL;
6189         r_texture_grey128 = NULL;
6190         r_texture_black = NULL;
6191         r_texture_whitecube = NULL;
6192         r_texture_normalizationcube = NULL;
6193         r_texture_fogattenuation = NULL;
6194         r_texture_gammaramps = NULL;
6195         r_texture_numcubemaps = 0;
6196         //r_texture_fogintensity = NULL;
6197         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6198         memset(&r_waterstate, 0, sizeof(r_waterstate));
6199         r_glsl_permutation = NULL;
6200         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6201         glslshaderstring = NULL;
6202 #ifdef SUPPORTCG
6203         r_cg_permutation = NULL;
6204         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
6205         cgshaderstring = NULL;
6206 #endif
6207         R_GLSL_Restart_f();
6208 }
6209
6210 extern void CL_ParseEntityLump(char *entitystring);
6211 void gl_main_newmap(void)
6212 {
6213         // FIXME: move this code to client
6214         int l;
6215         char *entities, entname[MAX_QPATH];
6216         if (r_qwskincache)
6217                 Mem_Free(r_qwskincache);
6218         r_qwskincache = NULL;
6219         r_qwskincache_size = 0;
6220         if (cl.worldmodel)
6221         {
6222                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
6223                 l = (int)strlen(entname) - 4;
6224                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
6225                 {
6226                         memcpy(entname + l, ".ent", 5);
6227                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
6228                         {
6229                                 CL_ParseEntityLump(entities);
6230                                 Mem_Free(entities);
6231                                 return;
6232                         }
6233                 }
6234                 if (cl.worldmodel->brush.entities)
6235                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
6236         }
6237         R_Main_FreeViewCache();
6238
6239         R_FrameData_Reset();
6240 }
6241
6242 void GL_Main_Init(void)
6243 {
6244         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
6245
6246         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
6247         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
6248         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
6249         if (gamemode == GAME_NEHAHRA)
6250         {
6251                 Cvar_RegisterVariable (&gl_fogenable);
6252                 Cvar_RegisterVariable (&gl_fogdensity);
6253                 Cvar_RegisterVariable (&gl_fogred);
6254                 Cvar_RegisterVariable (&gl_foggreen);
6255                 Cvar_RegisterVariable (&gl_fogblue);
6256                 Cvar_RegisterVariable (&gl_fogstart);
6257                 Cvar_RegisterVariable (&gl_fogend);
6258                 Cvar_RegisterVariable (&gl_skyclip);
6259         }
6260         Cvar_RegisterVariable(&r_motionblur);
6261         Cvar_RegisterVariable(&r_motionblur_maxblur);
6262         Cvar_RegisterVariable(&r_motionblur_bmin);
6263         Cvar_RegisterVariable(&r_motionblur_vmin);
6264         Cvar_RegisterVariable(&r_motionblur_vmax);
6265         Cvar_RegisterVariable(&r_motionblur_vcoeff);
6266         Cvar_RegisterVariable(&r_motionblur_randomize);
6267         Cvar_RegisterVariable(&r_damageblur);
6268         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
6269         Cvar_RegisterVariable(&r_equalize_entities_minambient);
6270         Cvar_RegisterVariable(&r_equalize_entities_by);
6271         Cvar_RegisterVariable(&r_equalize_entities_to);
6272         Cvar_RegisterVariable(&r_depthfirst);
6273         Cvar_RegisterVariable(&r_useinfinitefarclip);
6274         Cvar_RegisterVariable(&r_farclip_base);
6275         Cvar_RegisterVariable(&r_farclip_world);
6276         Cvar_RegisterVariable(&r_nearclip);
6277         Cvar_RegisterVariable(&r_showbboxes);
6278         Cvar_RegisterVariable(&r_showsurfaces);
6279         Cvar_RegisterVariable(&r_showtris);
6280         Cvar_RegisterVariable(&r_shownormals);
6281         Cvar_RegisterVariable(&r_showlighting);
6282         Cvar_RegisterVariable(&r_showshadowvolumes);
6283         Cvar_RegisterVariable(&r_showcollisionbrushes);
6284         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
6285         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
6286         Cvar_RegisterVariable(&r_showdisabledepthtest);
6287         Cvar_RegisterVariable(&r_drawportals);
6288         Cvar_RegisterVariable(&r_drawentities);
6289         Cvar_RegisterVariable(&r_cullentities_trace);
6290         Cvar_RegisterVariable(&r_cullentities_trace_samples);
6291         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
6292         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
6293         Cvar_RegisterVariable(&r_cullentities_trace_delay);
6294         Cvar_RegisterVariable(&r_drawviewmodel);
6295         Cvar_RegisterVariable(&r_speeds);
6296         Cvar_RegisterVariable(&r_fullbrights);
6297         Cvar_RegisterVariable(&r_wateralpha);
6298         Cvar_RegisterVariable(&r_dynamic);
6299         Cvar_RegisterVariable(&r_fullbright);
6300         Cvar_RegisterVariable(&r_shadows);
6301         Cvar_RegisterVariable(&r_shadows_darken);
6302         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
6303         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
6304         Cvar_RegisterVariable(&r_shadows_throwdistance);
6305         Cvar_RegisterVariable(&r_shadows_throwdirection);
6306         Cvar_RegisterVariable(&r_shadows_focus);
6307         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
6308         Cvar_RegisterVariable(&r_q1bsp_skymasking);
6309         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
6310         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
6311         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
6312         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
6313         Cvar_RegisterVariable(&r_fog_exp2);
6314         Cvar_RegisterVariable(&r_drawfog);
6315         Cvar_RegisterVariable(&r_transparentdepthmasking);
6316         Cvar_RegisterVariable(&r_texture_dds_load);
6317         Cvar_RegisterVariable(&r_texture_dds_save);
6318         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
6319         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
6320         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
6321         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
6322         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
6323         Cvar_RegisterVariable(&r_textureunits);
6324         Cvar_RegisterVariable(&gl_combine);
6325         Cvar_RegisterVariable(&r_glsl);
6326         Cvar_RegisterVariable(&r_glsl_deluxemapping);
6327         Cvar_RegisterVariable(&r_glsl_offsetmapping);
6328         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
6329         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
6330         Cvar_RegisterVariable(&r_glsl_postprocess);
6331         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
6332         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
6333         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
6334         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
6335         Cvar_RegisterVariable(&r_water);
6336         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
6337         Cvar_RegisterVariable(&r_water_clippingplanebias);
6338         Cvar_RegisterVariable(&r_water_refractdistort);
6339         Cvar_RegisterVariable(&r_water_reflectdistort);
6340         Cvar_RegisterVariable(&r_lerpsprites);
6341         Cvar_RegisterVariable(&r_lerpmodels);
6342         Cvar_RegisterVariable(&r_lerplightstyles);
6343         Cvar_RegisterVariable(&r_waterscroll);
6344         Cvar_RegisterVariable(&r_bloom);
6345         Cvar_RegisterVariable(&r_bloom_colorscale);
6346         Cvar_RegisterVariable(&r_bloom_brighten);
6347         Cvar_RegisterVariable(&r_bloom_blur);
6348         Cvar_RegisterVariable(&r_bloom_resolution);
6349         Cvar_RegisterVariable(&r_bloom_colorexponent);
6350         Cvar_RegisterVariable(&r_bloom_colorsubtract);
6351         Cvar_RegisterVariable(&r_hdr);
6352         Cvar_RegisterVariable(&r_hdr_scenebrightness);
6353         Cvar_RegisterVariable(&r_hdr_glowintensity);
6354         Cvar_RegisterVariable(&r_hdr_range);
6355         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
6356         Cvar_RegisterVariable(&developer_texturelogging);
6357         Cvar_RegisterVariable(&gl_lightmaps);
6358         Cvar_RegisterVariable(&r_test);
6359         Cvar_RegisterVariable(&r_batchmode);
6360         Cvar_RegisterVariable(&r_glsl_saturation);
6361         Cvar_RegisterVariable(&r_framedatasize);
6362         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
6363                 Cvar_SetValue("r_fullbrights", 0);
6364         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
6365
6366         Cvar_RegisterVariable(&r_track_sprites);
6367         Cvar_RegisterVariable(&r_track_sprites_flags);
6368         Cvar_RegisterVariable(&r_track_sprites_scalew);
6369         Cvar_RegisterVariable(&r_track_sprites_scaleh);
6370         Cvar_RegisterVariable(&r_overheadsprites_perspective);
6371         Cvar_RegisterVariable(&r_overheadsprites_pushback);
6372 }
6373
6374 extern void R_Textures_Init(void);
6375 extern void GL_Draw_Init(void);
6376 extern void GL_Main_Init(void);
6377 extern void R_Shadow_Init(void);
6378 extern void R_Sky_Init(void);
6379 extern void GL_Surf_Init(void);
6380 extern void R_Particles_Init(void);
6381 extern void R_Explosion_Init(void);
6382 extern void gl_backend_init(void);
6383 extern void Sbar_Init(void);
6384 extern void R_LightningBeams_Init(void);
6385 extern void Mod_RenderInit(void);
6386 extern void Font_Init(void);
6387
6388 void Render_Init(void)
6389 {
6390         gl_backend_init();
6391         R_Textures_Init();
6392         GL_Main_Init();
6393         Font_Init();
6394         GL_Draw_Init();
6395         R_Shadow_Init();
6396         R_Sky_Init();
6397         GL_Surf_Init();
6398         Sbar_Init();
6399         R_Particles_Init();
6400         R_Explosion_Init();
6401         R_LightningBeams_Init();
6402         Mod_RenderInit();
6403 }
6404
6405 /*
6406 ===============
6407 GL_Init
6408 ===============
6409 */
6410 extern char *ENGINE_EXTENSIONS;
6411 void GL_Init (void)
6412 {
6413         gl_renderer = (const char *)qglGetString(GL_RENDERER);
6414         gl_vendor = (const char *)qglGetString(GL_VENDOR);
6415         gl_version = (const char *)qglGetString(GL_VERSION);
6416         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
6417
6418         if (!gl_extensions)
6419                 gl_extensions = "";
6420         if (!gl_platformextensions)
6421                 gl_platformextensions = "";
6422
6423         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
6424         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
6425         Con_Printf("GL_VERSION: %s\n", gl_version);
6426         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
6427         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
6428
6429         VID_CheckExtensions();
6430
6431         // LordHavoc: report supported extensions
6432         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
6433
6434         // clear to black (loading plaque will be seen over this)
6435         CHECKGLERROR
6436         qglClearColor(0,0,0,1);CHECKGLERROR
6437         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
6438 }
6439
6440 int R_CullBox(const vec3_t mins, const vec3_t maxs)
6441 {
6442         int i;
6443         mplane_t *p;
6444         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6445         {
6446                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
6447                 if (i == 4)
6448                         continue;
6449                 p = r_refdef.view.frustum + i;
6450                 switch(p->signbits)
6451                 {
6452                 default:
6453                 case 0:
6454                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6455                                 return true;
6456                         break;
6457                 case 1:
6458                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6459                                 return true;
6460                         break;
6461                 case 2:
6462                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6463                                 return true;
6464                         break;
6465                 case 3:
6466                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6467                                 return true;
6468                         break;
6469                 case 4:
6470                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6471                                 return true;
6472                         break;
6473                 case 5:
6474                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6475                                 return true;
6476                         break;
6477                 case 6:
6478                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6479                                 return true;
6480                         break;
6481                 case 7:
6482                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6483                                 return true;
6484                         break;
6485                 }
6486         }
6487         return false;
6488 }
6489
6490 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
6491 {
6492         int i;
6493         const mplane_t *p;
6494         for (i = 0;i < numplanes;i++)
6495         {
6496                 p = planes + i;
6497                 switch(p->signbits)
6498                 {
6499                 default:
6500                 case 0:
6501                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6502                                 return true;
6503                         break;
6504                 case 1:
6505                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6506                                 return true;
6507                         break;
6508                 case 2:
6509                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6510                                 return true;
6511                         break;
6512                 case 3:
6513                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6514                                 return true;
6515                         break;
6516                 case 4:
6517                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6518                                 return true;
6519                         break;
6520                 case 5:
6521                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6522                                 return true;
6523                         break;
6524                 case 6:
6525                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6526                                 return true;
6527                         break;
6528                 case 7:
6529                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6530                                 return true;
6531                         break;
6532                 }
6533         }
6534         return false;
6535 }
6536
6537 //==================================================================================
6538
6539 // LordHavoc: this stores temporary data used within the same frame
6540
6541 qboolean r_framedata_failed;
6542 static size_t r_framedata_size;
6543 static size_t r_framedata_current;
6544 static void *r_framedata_base;
6545
6546 void R_FrameData_Reset(void)
6547 {
6548         if (r_framedata_base)
6549                 Mem_Free(r_framedata_base);
6550         r_framedata_base = NULL;
6551         r_framedata_size = 0;
6552         r_framedata_current = 0;
6553         r_framedata_failed = false;
6554 }
6555
6556 void R_FrameData_NewFrame(void)
6557 {
6558         size_t wantedsize;
6559         if (r_framedata_failed)
6560                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
6561         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
6562         wantedsize = bound(65536, wantedsize, 128*1024*1024);
6563         if (r_framedata_size != wantedsize)
6564         {
6565                 r_framedata_size = wantedsize;
6566                 if (r_framedata_base)
6567                         Mem_Free(r_framedata_base);
6568                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
6569         }
6570         r_framedata_current = 0;
6571         r_framedata_failed = false;
6572 }
6573
6574 void *R_FrameData_Alloc(size_t size)
6575 {
6576         void *data;
6577
6578         // align to 16 byte boundary
6579         size = (size + 15) & ~15;
6580         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
6581         r_framedata_current += size;
6582
6583         // check overflow
6584         if (r_framedata_current > r_framedata_size)
6585                 r_framedata_failed = true;
6586
6587         // return NULL on everything after a failure
6588         if (r_framedata_failed)
6589                 return NULL;
6590
6591         return data;
6592 }
6593
6594 void *R_FrameData_Store(size_t size, void *data)
6595 {
6596         void *d = R_FrameData_Alloc(size);
6597         if (d)
6598                 memcpy(d, data, size);
6599         return d;
6600 }
6601
6602 //==================================================================================
6603
6604 // LordHavoc: animcache originally written by Echon, rewritten since then
6605
6606 /**
6607  * Animation cache prevents re-generating mesh data for an animated model
6608  * multiple times in one frame for lighting, shadowing, reflections, etc.
6609  */
6610
6611 void R_AnimCache_Free(void)
6612 {
6613 }
6614
6615 void R_AnimCache_ClearCache(void)
6616 {
6617         int i;
6618         entity_render_t *ent;
6619
6620         for (i = 0;i < r_refdef.scene.numentities;i++)
6621         {
6622                 ent = r_refdef.scene.entities[i];
6623                 ent->animcache_vertex3f = NULL;
6624                 ent->animcache_normal3f = NULL;
6625                 ent->animcache_svector3f = NULL;
6626                 ent->animcache_tvector3f = NULL;
6627         }
6628 }
6629
6630 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6631 {
6632         dp_model_t *model = ent->model;
6633         int numvertices;
6634         // see if it's already cached this frame
6635         if (ent->animcache_vertex3f)
6636         {
6637                 // add normals/tangents if needed
6638                 if (wantnormals || wanttangents)
6639                 {
6640                         if (ent->animcache_normal3f)
6641                                 wantnormals = false;
6642                         if (ent->animcache_svector3f)
6643                                 wanttangents = false;
6644                         if (wantnormals || wanttangents)
6645                         {
6646                                 numvertices = model->surfmesh.num_vertices;
6647                                 if (wantnormals)
6648                                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6649                                 if (wanttangents)
6650                                 {
6651                                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6652                                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6653                                 }
6654                                 if (!r_framedata_failed)
6655                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
6656                         }
6657                 }
6658         }
6659         else
6660         {
6661                 // see if this ent is worth caching
6662                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
6663                         return false;
6664                 // get some memory for this entity and generate mesh data
6665                 numvertices = model->surfmesh.num_vertices;
6666                 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6667                 if (wantnormals)
6668                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6669                 if (wanttangents)
6670                 {
6671                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6672                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6673                 }
6674                 if (!r_framedata_failed)
6675                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
6676         }
6677         return !r_framedata_failed;
6678 }
6679
6680 void R_AnimCache_CacheVisibleEntities(void)
6681 {
6682         int i;
6683         qboolean wantnormals = !r_showsurfaces.integer;
6684         qboolean wanttangents = !r_showsurfaces.integer;
6685
6686         switch(vid.renderpath)
6687         {
6688         case RENDERPATH_GL20:
6689         case RENDERPATH_CGGL:
6690                 break;
6691         case RENDERPATH_GL13:
6692         case RENDERPATH_GL11:
6693                 wanttangents = false;
6694                 break;
6695         }
6696
6697         // TODO: thread this
6698         // NOTE: R_PrepareRTLights() also caches entities
6699
6700         for (i = 0;i < r_refdef.scene.numentities;i++)
6701                 if (r_refdef.viewcache.entityvisible[i])
6702                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
6703 }
6704
6705 //==================================================================================
6706
6707 static void R_View_UpdateEntityLighting (void)
6708 {
6709         int i;
6710         entity_render_t *ent;
6711         vec3_t tempdiffusenormal, avg;
6712         vec_t f, fa, fd, fdd;
6713         qboolean skipunseen = r_shadows.integer != 1 || R_Shadow_ShadowMappingEnabled();
6714
6715         for (i = 0;i < r_refdef.scene.numentities;i++)
6716         {
6717                 ent = r_refdef.scene.entities[i];
6718
6719                 // skip unseen models
6720                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
6721                         continue;
6722
6723                 // skip bsp models
6724                 if (ent->model && ent->model->brush.num_leafs)
6725                 {
6726                         // TODO: use modellight for r_ambient settings on world?
6727                         VectorSet(ent->modellight_ambient, 0, 0, 0);
6728                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
6729                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
6730                         continue;
6731                 }
6732
6733                 // fetch the lighting from the worldmodel data
6734                 VectorClear(ent->modellight_ambient);
6735                 VectorClear(ent->modellight_diffuse);
6736                 VectorClear(tempdiffusenormal);
6737                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
6738                 {
6739                         vec3_t org;
6740                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6741                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
6742                         if(ent->flags & RENDER_EQUALIZE)
6743                         {
6744                                 // first fix up ambient lighting...
6745                                 if(r_equalize_entities_minambient.value > 0)
6746                                 {
6747                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
6748                                         if(fd > 0)
6749                                         {
6750                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
6751                                                 if(fa < r_equalize_entities_minambient.value * fd)
6752                                                 {
6753                                                         // solve:
6754                                                         //   fa'/fd' = minambient
6755                                                         //   fa'+0.25*fd' = fa+0.25*fd
6756                                                         //   ...
6757                                                         //   fa' = fd' * minambient
6758                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
6759                                                         //   ...
6760                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
6761                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
6762                                                         //   ...
6763                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
6764                                                         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
6765                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
6766                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6767                                                 }
6768                                         }
6769                                 }
6770
6771                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
6772                                 {
6773                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
6774                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
6775                                         if(f > 0)
6776                                         {
6777                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
6778                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
6779                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6780                                         }
6781                                 }
6782                         }
6783                 }
6784                 else // highly rare
6785                         VectorSet(ent->modellight_ambient, 1, 1, 1);
6786
6787                 // move the light direction into modelspace coordinates for lighting code
6788                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
6789                 if(VectorLength2(ent->modellight_lightdir) == 0)
6790                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
6791                 VectorNormalize(ent->modellight_lightdir);
6792         }
6793 }
6794
6795 #define MAX_LINEOFSIGHTTRACES 64
6796
6797 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
6798 {
6799         int i;
6800         vec3_t boxmins, boxmaxs;
6801         vec3_t start;
6802         vec3_t end;
6803         dp_model_t *model = r_refdef.scene.worldmodel;
6804
6805         if (!model || !model->brush.TraceLineOfSight)
6806                 return true;
6807
6808         // expand the box a little
6809         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
6810         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
6811         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
6812         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
6813         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
6814         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
6815
6816         // return true if eye is inside enlarged box
6817         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
6818                 return true;
6819
6820         // try center
6821         VectorCopy(eye, start);
6822         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
6823         if (model->brush.TraceLineOfSight(model, start, end))
6824                 return true;
6825
6826         // try various random positions
6827         for (i = 0;i < numsamples;i++)
6828         {
6829                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
6830                 if (model->brush.TraceLineOfSight(model, start, end))
6831                         return true;
6832         }
6833
6834         return false;
6835 }
6836
6837
6838 static void R_View_UpdateEntityVisible (void)
6839 {
6840         int i;
6841         int renderimask;
6842         int samples;
6843         entity_render_t *ent;
6844
6845         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
6846                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
6847                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
6848                 :                                                          RENDER_EXTERIORMODEL;
6849         if (!r_drawviewmodel.integer)
6850                 renderimask |= RENDER_VIEWMODEL;
6851         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
6852         {
6853                 // worldmodel can check visibility
6854                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
6855                 for (i = 0;i < r_refdef.scene.numentities;i++)
6856                 {
6857                         ent = r_refdef.scene.entities[i];
6858                         if (!(ent->flags & renderimask))
6859                         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)))
6860                         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))
6861                                 r_refdef.viewcache.entityvisible[i] = true;
6862                 }
6863                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
6864                 {
6865                         for (i = 0;i < r_refdef.scene.numentities;i++)
6866                         {
6867                                 ent = r_refdef.scene.entities[i];
6868                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
6869                                 {
6870                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
6871                                         if (samples < 0)
6872                                                 continue; // temp entities do pvs only
6873                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
6874                                                 ent->last_trace_visibility = realtime;
6875                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
6876                                                 r_refdef.viewcache.entityvisible[i] = 0;
6877                                 }
6878                         }
6879                 }
6880         }
6881         else
6882         {
6883                 // no worldmodel or it can't check visibility
6884                 for (i = 0;i < r_refdef.scene.numentities;i++)
6885                 {
6886                         ent = r_refdef.scene.entities[i];
6887                         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));
6888                 }
6889         }
6890 }
6891
6892 /// only used if skyrendermasked, and normally returns false
6893 int R_DrawBrushModelsSky (void)
6894 {
6895         int i, sky;
6896         entity_render_t *ent;
6897
6898         sky = false;
6899         for (i = 0;i < r_refdef.scene.numentities;i++)
6900         {
6901                 if (!r_refdef.viewcache.entityvisible[i])
6902                         continue;
6903                 ent = r_refdef.scene.entities[i];
6904                 if (!ent->model || !ent->model->DrawSky)
6905                         continue;
6906                 ent->model->DrawSky(ent);
6907                 sky = true;
6908         }
6909         return sky;
6910 }
6911
6912 static void R_DrawNoModel(entity_render_t *ent);
6913 static void R_DrawModels(void)
6914 {
6915         int i;
6916         entity_render_t *ent;
6917
6918         for (i = 0;i < r_refdef.scene.numentities;i++)
6919         {
6920                 if (!r_refdef.viewcache.entityvisible[i])
6921                         continue;
6922                 ent = r_refdef.scene.entities[i];
6923                 r_refdef.stats.entities++;
6924                 if (ent->model && ent->model->Draw != NULL)
6925                         ent->model->Draw(ent);
6926                 else
6927                         R_DrawNoModel(ent);
6928         }
6929 }
6930
6931 static void R_DrawModelsDepth(void)
6932 {
6933         int i;
6934         entity_render_t *ent;
6935
6936         for (i = 0;i < r_refdef.scene.numentities;i++)
6937         {
6938                 if (!r_refdef.viewcache.entityvisible[i])
6939                         continue;
6940                 ent = r_refdef.scene.entities[i];
6941                 if (ent->model && ent->model->DrawDepth != NULL)
6942                         ent->model->DrawDepth(ent);
6943         }
6944 }
6945
6946 static void R_DrawModelsDebug(void)
6947 {
6948         int i;
6949         entity_render_t *ent;
6950
6951         for (i = 0;i < r_refdef.scene.numentities;i++)
6952         {
6953                 if (!r_refdef.viewcache.entityvisible[i])
6954                         continue;
6955                 ent = r_refdef.scene.entities[i];
6956                 if (ent->model && ent->model->DrawDebug != NULL)
6957                         ent->model->DrawDebug(ent);
6958         }
6959 }
6960
6961 static void R_DrawModelsAddWaterPlanes(void)
6962 {
6963         int i;
6964         entity_render_t *ent;
6965
6966         for (i = 0;i < r_refdef.scene.numentities;i++)
6967         {
6968                 if (!r_refdef.viewcache.entityvisible[i])
6969                         continue;
6970                 ent = r_refdef.scene.entities[i];
6971                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
6972                         ent->model->DrawAddWaterPlanes(ent);
6973         }
6974 }
6975
6976 static void R_View_SetFrustum(void)
6977 {
6978         int i;
6979         double slopex, slopey;
6980         vec3_t forward, left, up, origin;
6981
6982         // we can't trust r_refdef.view.forward and friends in reflected scenes
6983         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
6984
6985 #if 0
6986         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
6987         r_refdef.view.frustum[0].normal[1] = 0 - 0;
6988         r_refdef.view.frustum[0].normal[2] = -1 - 0;
6989         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
6990         r_refdef.view.frustum[1].normal[1] = 0 + 0;
6991         r_refdef.view.frustum[1].normal[2] = -1 + 0;
6992         r_refdef.view.frustum[2].normal[0] = 0 - 0;
6993         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
6994         r_refdef.view.frustum[2].normal[2] = -1 - 0;
6995         r_refdef.view.frustum[3].normal[0] = 0 + 0;
6996         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
6997         r_refdef.view.frustum[3].normal[2] = -1 + 0;
6998 #endif
6999
7000 #if 0
7001         zNear = r_refdef.nearclip;
7002         nudge = 1.0 - 1.0 / (1<<23);
7003         r_refdef.view.frustum[4].normal[0] = 0 - 0;
7004         r_refdef.view.frustum[4].normal[1] = 0 - 0;
7005         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
7006         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
7007         r_refdef.view.frustum[5].normal[0] = 0 + 0;
7008         r_refdef.view.frustum[5].normal[1] = 0 + 0;
7009         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
7010         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
7011 #endif
7012
7013
7014
7015 #if 0
7016         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
7017         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
7018         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
7019         r_refdef.view.frustum[0].dist = m[15] - m[12];
7020
7021         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
7022         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
7023         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
7024         r_refdef.view.frustum[1].dist = m[15] + m[12];
7025
7026         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
7027         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
7028         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
7029         r_refdef.view.frustum[2].dist = m[15] - m[13];
7030
7031         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
7032         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
7033         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
7034         r_refdef.view.frustum[3].dist = m[15] + m[13];
7035
7036         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
7037         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
7038         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
7039         r_refdef.view.frustum[4].dist = m[15] - m[14];
7040
7041         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
7042         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
7043         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
7044         r_refdef.view.frustum[5].dist = m[15] + m[14];
7045 #endif
7046
7047         if (r_refdef.view.useperspective)
7048         {
7049                 slopex = 1.0 / r_refdef.view.frustum_x;
7050                 slopey = 1.0 / r_refdef.view.frustum_y;
7051                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
7052                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
7053                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
7054                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
7055                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7056
7057                 // Leaving those out was a mistake, those were in the old code, and they
7058                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
7059                 // I couldn't reproduce it after adding those normalizations. --blub
7060                 VectorNormalize(r_refdef.view.frustum[0].normal);
7061                 VectorNormalize(r_refdef.view.frustum[1].normal);
7062                 VectorNormalize(r_refdef.view.frustum[2].normal);
7063                 VectorNormalize(r_refdef.view.frustum[3].normal);
7064
7065                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
7066                 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]);
7067                 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]);
7068                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * r_refdef.view.frustum_x, left,  1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[2]);
7069                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward,  1024 * r_refdef.view.frustum_x, left,  1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]);
7070
7071                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
7072                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
7073                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
7074                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
7075                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7076         }
7077         else
7078         {
7079                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
7080                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
7081                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
7082                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
7083                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7084                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
7085                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
7086                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
7087                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
7088                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7089         }
7090         r_refdef.view.numfrustumplanes = 5;
7091
7092         if (r_refdef.view.useclipplane)
7093         {
7094                 r_refdef.view.numfrustumplanes = 6;
7095                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
7096         }
7097
7098         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7099                 PlaneClassify(r_refdef.view.frustum + i);
7100
7101         // LordHavoc: note to all quake engine coders, Quake had a special case
7102         // for 90 degrees which assumed a square view (wrong), so I removed it,
7103         // Quake2 has it disabled as well.
7104
7105         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
7106         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
7107         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
7108         //PlaneClassify(&frustum[0]);
7109
7110         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
7111         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
7112         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
7113         //PlaneClassify(&frustum[1]);
7114
7115         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
7116         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
7117         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
7118         //PlaneClassify(&frustum[2]);
7119
7120         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
7121         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
7122         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
7123         //PlaneClassify(&frustum[3]);
7124
7125         // nearclip plane
7126         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
7127         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
7128         //PlaneClassify(&frustum[4]);
7129 }
7130
7131 void R_View_Update(void)
7132 {
7133         R_Main_ResizeViewCache();
7134         R_View_SetFrustum();
7135         R_View_WorldVisibility(r_refdef.view.useclipplane);
7136         R_View_UpdateEntityVisible();
7137         R_View_UpdateEntityLighting();
7138 }
7139
7140 void R_SetupView(qboolean allowwaterclippingplane)
7141 {
7142         const float *customclipplane = NULL;
7143         float plane[4];
7144         if (r_refdef.view.useclipplane && allowwaterclippingplane)
7145         {
7146                 // LordHavoc: couldn't figure out how to make this approach the
7147                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
7148                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
7149                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
7150                         dist = r_refdef.view.clipplane.dist;
7151                 plane[0] = r_refdef.view.clipplane.normal[0];
7152                 plane[1] = r_refdef.view.clipplane.normal[1];
7153                 plane[2] = r_refdef.view.clipplane.normal[2];
7154                 plane[3] = dist;
7155                 customclipplane = plane;
7156         }
7157
7158         if (!r_refdef.view.useperspective)
7159                 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);
7160         else if (vid.stencil && r_useinfinitefarclip.integer)
7161                 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);
7162         else
7163                 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);
7164         R_SetViewport(&r_refdef.view.viewport);
7165 }
7166
7167 void R_EntityMatrix(const matrix4x4_t *matrix)
7168 {
7169         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
7170         {
7171                 gl_modelmatrixchanged = false;
7172                 gl_modelmatrix = *matrix;
7173                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
7174                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
7175                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
7176                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
7177                 CHECKGLERROR
7178                 switch(vid.renderpath)
7179                 {
7180                 case RENDERPATH_GL20:
7181                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
7182                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
7183                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7184                         break;
7185                 case RENDERPATH_CGGL:
7186 #ifdef SUPPORTCG
7187                         CHECKCGERROR
7188                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
7189                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
7190                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7191 #endif
7192                         break;
7193                 case RENDERPATH_GL13:
7194                 case RENDERPATH_GL11:
7195                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7196                         break;
7197                 }
7198         }
7199 }
7200
7201 void R_ResetViewRendering2D(void)
7202 {
7203         r_viewport_t viewport;
7204         DrawQ_Finish();
7205
7206         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
7207         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);
7208         R_SetViewport(&viewport);
7209         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
7210         GL_Color(1, 1, 1, 1);
7211         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7212         GL_BlendFunc(GL_ONE, GL_ZERO);
7213         GL_AlphaTest(false);
7214         GL_ScissorTest(false);
7215         GL_DepthMask(false);
7216         GL_DepthRange(0, 1);
7217         GL_DepthTest(false);
7218         R_EntityMatrix(&identitymatrix);
7219         R_Mesh_ResetTextureState();
7220         GL_PolygonOffset(0, 0);
7221         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7222         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7223         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7224         qglStencilMask(~0);CHECKGLERROR
7225         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7226         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7227         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
7228 }
7229
7230 void R_ResetViewRendering3D(void)
7231 {
7232         DrawQ_Finish();
7233
7234         R_SetupView(true);
7235         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7236         GL_Color(1, 1, 1, 1);
7237         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7238         GL_BlendFunc(GL_ONE, GL_ZERO);
7239         GL_AlphaTest(false);
7240         GL_ScissorTest(true);
7241         GL_DepthMask(true);
7242         GL_DepthRange(0, 1);
7243         GL_DepthTest(true);
7244         R_EntityMatrix(&identitymatrix);
7245         R_Mesh_ResetTextureState();
7246         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7247         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7248         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7249         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7250         qglStencilMask(~0);CHECKGLERROR
7251         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7252         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7253         GL_CullFace(r_refdef.view.cullface_back);
7254 }
7255
7256 void R_RenderScene(void);
7257 void R_RenderWaterPlanes(void);
7258
7259 static void R_Water_StartFrame(void)
7260 {
7261         int i;
7262         int waterwidth, waterheight, texturewidth, textureheight;
7263         r_waterstate_waterplane_t *p;
7264
7265         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
7266                 return;
7267
7268         switch(vid.renderpath)
7269         {
7270         case RENDERPATH_GL20:
7271         case RENDERPATH_CGGL:
7272                 break;
7273         case RENDERPATH_GL13:
7274         case RENDERPATH_GL11:
7275                 return;
7276         }
7277
7278         // set waterwidth and waterheight to the water resolution that will be
7279         // used (often less than the screen resolution for faster rendering)
7280         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
7281         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
7282
7283         // calculate desired texture sizes
7284         // can't use water if the card does not support the texture size
7285         if (!r_water.integer || r_showsurfaces.integer)
7286                 texturewidth = textureheight = waterwidth = waterheight = 0;
7287         else if (vid.support.arb_texture_non_power_of_two)
7288         {
7289                 texturewidth = waterwidth;
7290                 textureheight = waterheight;
7291         }
7292         else
7293         {
7294                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
7295                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
7296         }
7297
7298         // allocate textures as needed
7299         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
7300         {
7301                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7302                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
7303                 {
7304                         if (p->texture_refraction)
7305                                 R_FreeTexture(p->texture_refraction);
7306                         p->texture_refraction = NULL;
7307                         if (p->texture_reflection)
7308                                 R_FreeTexture(p->texture_reflection);
7309                         p->texture_reflection = NULL;
7310                 }
7311                 memset(&r_waterstate, 0, sizeof(r_waterstate));
7312                 r_waterstate.texturewidth = texturewidth;
7313                 r_waterstate.textureheight = textureheight;
7314         }
7315
7316         if (r_waterstate.texturewidth)
7317         {
7318                 r_waterstate.enabled = true;
7319
7320                 // when doing a reduced render (HDR) we want to use a smaller area
7321                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
7322                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
7323
7324                 // set up variables that will be used in shader setup
7325                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7326                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7327                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7328                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7329         }
7330
7331         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7332         r_waterstate.numwaterplanes = 0;
7333 }
7334
7335 void R_Water_AddWaterPlane(msurface_t *surface)
7336 {
7337         int triangleindex, planeindex;
7338         const int *e;
7339         vec3_t vert[3];
7340         vec3_t normal;
7341         vec3_t center;
7342         mplane_t plane;
7343         r_waterstate_waterplane_t *p;
7344         texture_t *t = R_GetCurrentTexture(surface->texture);
7345         // just use the first triangle with a valid normal for any decisions
7346         VectorClear(normal);
7347         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
7348         {
7349                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
7350                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
7351                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
7352                 TriangleNormal(vert[0], vert[1], vert[2], normal);
7353                 if (VectorLength2(normal) >= 0.001)
7354                         break;
7355         }
7356
7357         VectorCopy(normal, plane.normal);
7358         VectorNormalize(plane.normal);
7359         plane.dist = DotProduct(vert[0], plane.normal);
7360         PlaneClassify(&plane);
7361         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
7362         {
7363                 // skip backfaces (except if nocullface is set)
7364                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
7365                         return;
7366                 VectorNegate(plane.normal, plane.normal);
7367                 plane.dist *= -1;
7368                 PlaneClassify(&plane);
7369         }
7370
7371
7372         // find a matching plane if there is one
7373         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7374                 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
7375                         break;
7376         if (planeindex >= r_waterstate.maxwaterplanes)
7377                 return; // nothing we can do, out of planes
7378
7379         // if this triangle does not fit any known plane rendered this frame, add one
7380         if (planeindex >= r_waterstate.numwaterplanes)
7381         {
7382                 // store the new plane
7383                 r_waterstate.numwaterplanes++;
7384                 p->plane = plane;
7385                 // clear materialflags and pvs
7386                 p->materialflags = 0;
7387                 p->pvsvalid = false;
7388         }
7389         // merge this surface's materialflags into the waterplane
7390         p->materialflags |= t->currentmaterialflags;
7391         // merge this surface's PVS into the waterplane
7392         VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
7393         if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
7394          && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
7395         {
7396                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
7397                 p->pvsvalid = true;
7398         }
7399 }
7400
7401 static void R_Water_ProcessPlanes(void)
7402 {
7403         r_refdef_view_t originalview;
7404         r_refdef_view_t myview;
7405         int planeindex;
7406         r_waterstate_waterplane_t *p;
7407
7408         originalview = r_refdef.view;
7409
7410         // make sure enough textures are allocated
7411         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7412         {
7413                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7414                 {
7415                         if (!p->texture_refraction)
7416                                 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);
7417                         if (!p->texture_refraction)
7418                                 goto error;
7419                 }
7420
7421                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7422                 {
7423                         if (!p->texture_reflection)
7424                                 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);
7425                         if (!p->texture_reflection)
7426                                 goto error;
7427                 }
7428         }
7429
7430         // render views
7431         r_refdef.view = originalview;
7432         r_refdef.view.showdebug = false;
7433         r_refdef.view.width = r_waterstate.waterwidth;
7434         r_refdef.view.height = r_waterstate.waterheight;
7435         r_refdef.view.useclipplane = true;
7436         myview = r_refdef.view;
7437         r_waterstate.renderingscene = true;
7438         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7439         {
7440                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7441                 {
7442                         r_refdef.view = myview;
7443                         // render reflected scene and copy into texture
7444                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
7445                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
7446                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
7447                         r_refdef.view.clipplane = p->plane;
7448                         // reverse the cullface settings for this render
7449                         r_refdef.view.cullface_front = GL_FRONT;
7450                         r_refdef.view.cullface_back = GL_BACK;
7451                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
7452                         {
7453                                 r_refdef.view.usecustompvs = true;
7454                                 if (p->pvsvalid)
7455                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7456                                 else
7457                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7458                         }
7459
7460                         R_ResetViewRendering3D();
7461                         R_ClearScreen(r_refdef.fogenabled);
7462                         R_View_Update();
7463                         R_RenderScene();
7464
7465                         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);
7466                 }
7467
7468                 // render the normal view scene and copy into texture
7469                 // (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)
7470                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7471                 {
7472                         r_waterstate.renderingrefraction = true;
7473                         r_refdef.view = myview;
7474                         r_refdef.view.clipplane = p->plane;
7475                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
7476                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
7477                         PlaneClassify(&r_refdef.view.clipplane);
7478
7479                         R_ResetViewRendering3D();
7480                         R_ClearScreen(r_refdef.fogenabled);
7481                         R_View_Update();
7482                         R_RenderScene();
7483
7484                         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);
7485                         r_waterstate.renderingrefraction = false;
7486                 }
7487
7488         }
7489         r_waterstate.renderingscene = false;
7490         r_refdef.view = originalview;
7491         R_ResetViewRendering3D();
7492         R_ClearScreen(r_refdef.fogenabled);
7493         R_View_Update();
7494         return;
7495 error:
7496         r_refdef.view = originalview;
7497         r_waterstate.renderingscene = false;
7498         Cvar_SetValueQuick(&r_water, 0);
7499         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
7500         return;
7501 }
7502
7503 void R_Bloom_StartFrame(void)
7504 {
7505         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
7506
7507         switch(vid.renderpath)
7508         {
7509         case RENDERPATH_GL20:
7510         case RENDERPATH_CGGL:
7511                 break;
7512         case RENDERPATH_GL13:
7513         case RENDERPATH_GL11:
7514                 return;
7515         }
7516
7517         // set bloomwidth and bloomheight to the bloom resolution that will be
7518         // used (often less than the screen resolution for faster rendering)
7519         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
7520         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
7521         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
7522         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
7523         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
7524
7525         // calculate desired texture sizes
7526         if (vid.support.arb_texture_non_power_of_two)
7527         {
7528                 screentexturewidth = r_refdef.view.width;
7529                 screentextureheight = r_refdef.view.height;
7530                 bloomtexturewidth = r_bloomstate.bloomwidth;
7531                 bloomtextureheight = r_bloomstate.bloomheight;
7532         }
7533         else
7534         {
7535                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
7536                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
7537                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
7538                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
7539         }
7540
7541         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))
7542         {
7543                 Cvar_SetValueQuick(&r_hdr, 0);
7544                 Cvar_SetValueQuick(&r_bloom, 0);
7545                 Cvar_SetValueQuick(&r_motionblur, 0);
7546                 Cvar_SetValueQuick(&r_damageblur, 0);
7547         }
7548
7549         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)))
7550                 screentexturewidth = screentextureheight = 0;
7551         if (!r_hdr.integer && !r_bloom.integer)
7552                 bloomtexturewidth = bloomtextureheight = 0;
7553
7554         // allocate textures as needed
7555         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
7556         {
7557                 if (r_bloomstate.texture_screen)
7558                         R_FreeTexture(r_bloomstate.texture_screen);
7559                 r_bloomstate.texture_screen = NULL;
7560                 r_bloomstate.screentexturewidth = screentexturewidth;
7561                 r_bloomstate.screentextureheight = screentextureheight;
7562                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
7563                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
7564         }
7565         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
7566         {
7567                 if (r_bloomstate.texture_bloom)
7568                         R_FreeTexture(r_bloomstate.texture_bloom);
7569                 r_bloomstate.texture_bloom = NULL;
7570                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
7571                 r_bloomstate.bloomtextureheight = bloomtextureheight;
7572                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
7573                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7574         }
7575
7576         // when doing a reduced render (HDR) we want to use a smaller area
7577         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
7578         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
7579         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
7580         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
7581         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
7582
7583         // set up a texcoord array for the full resolution screen image
7584         // (we have to keep this around to copy back during final render)
7585         r_bloomstate.screentexcoord2f[0] = 0;
7586         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7587         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7588         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7589         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7590         r_bloomstate.screentexcoord2f[5] = 0;
7591         r_bloomstate.screentexcoord2f[6] = 0;
7592         r_bloomstate.screentexcoord2f[7] = 0;
7593
7594         // set up a texcoord array for the reduced resolution bloom image
7595         // (which will be additive blended over the screen image)
7596         r_bloomstate.bloomtexcoord2f[0] = 0;
7597         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7598         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7599         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7600         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7601         r_bloomstate.bloomtexcoord2f[5] = 0;
7602         r_bloomstate.bloomtexcoord2f[6] = 0;
7603         r_bloomstate.bloomtexcoord2f[7] = 0;
7604
7605         if (r_hdr.integer || r_bloom.integer)
7606         {
7607                 r_bloomstate.enabled = true;
7608                 r_bloomstate.hdr = r_hdr.integer != 0;
7609         }
7610
7611         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);
7612 }
7613
7614 void R_Bloom_CopyBloomTexture(float colorscale)
7615 {
7616         r_refdef.stats.bloom++;
7617
7618         // scale down screen texture to the bloom texture size
7619         CHECKGLERROR
7620         R_SetViewport(&r_bloomstate.viewport);
7621         GL_BlendFunc(GL_ONE, GL_ZERO);
7622         GL_Color(colorscale, colorscale, colorscale, 1);
7623         // TODO: optimize with multitexture or GLSL
7624         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7625         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7626         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7627         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7628
7629         // we now have a bloom image in the framebuffer
7630         // copy it into the bloom image texture for later processing
7631         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);
7632         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7633 }
7634
7635 void R_Bloom_CopyHDRTexture(void)
7636 {
7637         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);
7638         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7639 }
7640
7641 void R_Bloom_MakeTexture(void)
7642 {
7643         int x, range, dir;
7644         float xoffset, yoffset, r, brighten;
7645
7646         r_refdef.stats.bloom++;
7647
7648         R_ResetViewRendering2D();
7649         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7650         R_Mesh_ColorPointer(NULL, 0, 0);
7651
7652         // we have a bloom image in the framebuffer
7653         CHECKGLERROR
7654         R_SetViewport(&r_bloomstate.viewport);
7655
7656         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
7657         {
7658                 x *= 2;
7659                 r = bound(0, r_bloom_colorexponent.value / x, 1);
7660                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7661                 GL_Color(r, r, r, 1);
7662                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7663                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7664                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7665                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7666
7667                 // copy the vertically blurred bloom view to a texture
7668                 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);
7669                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7670         }
7671
7672         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
7673         brighten = r_bloom_brighten.value;
7674         if (r_hdr.integer)
7675                 brighten *= r_hdr_range.value;
7676         brighten = sqrt(brighten);
7677         if(range >= 1)
7678                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
7679         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7680         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
7681
7682         for (dir = 0;dir < 2;dir++)
7683         {
7684                 // blend on at multiple vertical offsets to achieve a vertical blur
7685                 // TODO: do offset blends using GLSL
7686                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
7687                 GL_BlendFunc(GL_ONE, GL_ZERO);
7688                 for (x = -range;x <= range;x++)
7689                 {
7690                         if (!dir){xoffset = 0;yoffset = x;}
7691                         else {xoffset = x;yoffset = 0;}
7692                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
7693                         yoffset /= (float)r_bloomstate.bloomtextureheight;
7694                         // compute a texcoord array with the specified x and y offset
7695                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
7696                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7697                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7698                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7699                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7700                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
7701                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
7702                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
7703                         // this r value looks like a 'dot' particle, fading sharply to
7704                         // black at the edges
7705                         // (probably not realistic but looks good enough)
7706                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
7707                         //r = brighten/(range*2+1);
7708                         r = brighten / (range * 2 + 1);
7709                         if(range >= 1)
7710                                 r *= (1 - x*x/(float)(range*range));
7711                         GL_Color(r, r, r, 1);
7712                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7713                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7714                         GL_BlendFunc(GL_ONE, GL_ONE);
7715                 }
7716
7717                 // copy the vertically blurred bloom view to a texture
7718                 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);
7719                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7720         }
7721
7722         // apply subtract last
7723         // (just like it would be in a GLSL shader)
7724         if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
7725         {
7726                 GL_BlendFunc(GL_ONE, GL_ZERO);
7727                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7728                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7729                 GL_Color(1, 1, 1, 1);
7730                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7731                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7732
7733                 GL_BlendFunc(GL_ONE, GL_ONE);
7734                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
7735                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7736                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7737                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
7738                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7739                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7740                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
7741
7742                 // copy the darkened bloom view to a texture
7743                 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);
7744                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7745         }
7746 }
7747
7748 void R_HDR_RenderBloomTexture(void)
7749 {
7750         int oldwidth, oldheight;
7751         float oldcolorscale;
7752
7753         oldcolorscale = r_refdef.view.colorscale;
7754         oldwidth = r_refdef.view.width;
7755         oldheight = r_refdef.view.height;
7756         r_refdef.view.width = r_bloomstate.bloomwidth;
7757         r_refdef.view.height = r_bloomstate.bloomheight;
7758
7759         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
7760         // TODO: add exposure compensation features
7761         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
7762
7763         r_refdef.view.showdebug = false;
7764         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
7765
7766         R_ResetViewRendering3D();
7767
7768         R_ClearScreen(r_refdef.fogenabled);
7769         if (r_timereport_active)
7770                 R_TimeReport("HDRclear");
7771
7772         R_View_Update();
7773         if (r_timereport_active)
7774                 R_TimeReport("visibility");
7775
7776         // only do secondary renders with HDR if r_hdr is 2 or higher
7777         r_waterstate.numwaterplanes = 0;
7778         if (r_waterstate.enabled && r_hdr.integer >= 2)
7779                 R_RenderWaterPlanes();
7780
7781         r_refdef.view.showdebug = true;
7782         R_RenderScene();
7783         r_waterstate.numwaterplanes = 0;
7784
7785         R_ResetViewRendering2D();
7786
7787         R_Bloom_CopyHDRTexture();
7788         R_Bloom_MakeTexture();
7789
7790         // restore the view settings
7791         r_refdef.view.width = oldwidth;
7792         r_refdef.view.height = oldheight;
7793         r_refdef.view.colorscale = oldcolorscale;
7794
7795         R_ResetViewRendering3D();
7796
7797         R_ClearScreen(r_refdef.fogenabled);
7798         if (r_timereport_active)
7799                 R_TimeReport("viewclear");
7800 }
7801
7802 static void R_BlendView(void)
7803 {
7804         unsigned int permutation;
7805         float uservecs[4][4];
7806
7807         switch (vid.renderpath)
7808         {
7809         case RENDERPATH_GL20:
7810         case RENDERPATH_CGGL:
7811                 permutation =
7812                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
7813                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
7814                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
7815                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
7816                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
7817
7818                 if (r_bloomstate.texture_screen)
7819                 {
7820                         // make sure the buffer is available
7821                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
7822
7823                         R_ResetViewRendering2D();
7824                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7825                         R_Mesh_ColorPointer(NULL, 0, 0);
7826
7827                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
7828                         {
7829                                 // declare variables
7830                                 float speed;
7831                                 static float avgspeed;
7832
7833                                 speed = VectorLength(cl.movement_velocity);
7834
7835                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
7836                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
7837
7838                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
7839                                 speed = bound(0, speed, 1);
7840                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
7841
7842                                 // calculate values into a standard alpha
7843                                 cl.motionbluralpha = 1 - exp(-
7844                                                 (
7845                                                  (r_motionblur.value * speed / 80)
7846                                                  +
7847                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
7848                                                 )
7849                                                 /
7850                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
7851                                            );
7852
7853                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
7854                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
7855                                 // apply the blur
7856                                 if (cl.motionbluralpha > 0)
7857                                 {
7858                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7859                                         GL_Color(1, 1, 1, cl.motionbluralpha);
7860                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7861                                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7862                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7863                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7864                                 }
7865                         }
7866
7867                         // copy view into the screen texture
7868                         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);
7869                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7870                 }
7871                 else if (!r_bloomstate.texture_bloom)
7872                 {
7873                         // we may still have to do view tint...
7874                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7875                         {
7876                                 // apply a color tint to the whole view
7877                                 R_ResetViewRendering2D();
7878                                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7879                                 R_Mesh_ColorPointer(NULL, 0, 0);
7880                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7881                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7882                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7883                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7884                         }
7885                         break; // no screen processing, no bloom, skip it
7886                 }
7887
7888                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
7889                 {
7890                         // render simple bloom effect
7891                         // copy the screen and shrink it and darken it for the bloom process
7892                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
7893                         // make the bloom texture
7894                         R_Bloom_MakeTexture();
7895                 }
7896
7897 #if _MSC_VER >= 1400
7898 #define sscanf sscanf_s
7899 #endif
7900                 memset(uservecs, 0, sizeof(uservecs));
7901                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
7902                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
7903                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
7904                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
7905
7906                 R_ResetViewRendering2D();
7907                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7908                 R_Mesh_ColorPointer(NULL, 0, 0);
7909                 GL_Color(1, 1, 1, 1);
7910                 GL_BlendFunc(GL_ONE, GL_ZERO);
7911                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7912                 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7913
7914                 switch(vid.renderpath)
7915                 {
7916                 case RENDERPATH_GL20:
7917                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
7918                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
7919                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
7920                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
7921                         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]);
7922                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
7923                         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]);
7924                         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]);
7925                         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]);
7926                         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]);
7927                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
7928                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
7929                         break;
7930                 case RENDERPATH_CGGL:
7931 #ifdef SUPPORTCG
7932                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
7933                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
7934                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
7935                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
7936                         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
7937                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
7938                         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
7939                         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
7940                         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
7941                         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
7942                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
7943                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
7944 #endif
7945                         break;
7946                 default:
7947                         break;
7948                 }
7949                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7950                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7951                 break;
7952         case RENDERPATH_GL13:
7953         case RENDERPATH_GL11:
7954                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7955                 {
7956                         // apply a color tint to the whole view
7957                         R_ResetViewRendering2D();
7958                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7959                         R_Mesh_ColorPointer(NULL, 0, 0);
7960                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7961                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7962                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7963                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7964                 }
7965                 break;
7966         }
7967 }
7968
7969 matrix4x4_t r_waterscrollmatrix;
7970
7971 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
7972 {
7973         if (r_refdef.fog_density)
7974         {
7975                 r_refdef.fogcolor[0] = r_refdef.fog_red;
7976                 r_refdef.fogcolor[1] = r_refdef.fog_green;
7977                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7978
7979                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7980                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7981                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7982                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7983
7984                 {
7985                         vec3_t fogvec;
7986                         VectorCopy(r_refdef.fogcolor, fogvec);
7987                         //   color.rgb *= ContrastBoost * SceneBrightness;
7988                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7989                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7990                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7991                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7992                 }
7993         }
7994 }
7995
7996 void R_UpdateVariables(void)
7997 {
7998         R_Textures_Frame();
7999
8000         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
8001
8002         r_refdef.farclip = r_farclip_base.value;
8003         if (r_refdef.scene.worldmodel)
8004                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
8005         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
8006
8007         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
8008                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
8009         r_refdef.polygonfactor = 0;
8010         r_refdef.polygonoffset = 0;
8011         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8012         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8013
8014         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
8015         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
8016         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
8017         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
8018         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
8019         if (r_showsurfaces.integer)
8020         {
8021                 r_refdef.scene.rtworld = false;
8022                 r_refdef.scene.rtworldshadows = false;
8023                 r_refdef.scene.rtdlight = false;
8024                 r_refdef.scene.rtdlightshadows = false;
8025                 r_refdef.lightmapintensity = 0;
8026         }
8027
8028         if (gamemode == GAME_NEHAHRA)
8029         {
8030                 if (gl_fogenable.integer)
8031                 {
8032                         r_refdef.oldgl_fogenable = true;
8033                         r_refdef.fog_density = gl_fogdensity.value;
8034                         r_refdef.fog_red = gl_fogred.value;
8035                         r_refdef.fog_green = gl_foggreen.value;
8036                         r_refdef.fog_blue = gl_fogblue.value;
8037                         r_refdef.fog_alpha = 1;
8038                         r_refdef.fog_start = 0;
8039                         r_refdef.fog_end = gl_skyclip.value;
8040                         r_refdef.fog_height = 1<<30;
8041                         r_refdef.fog_fadedepth = 128;
8042                 }
8043                 else if (r_refdef.oldgl_fogenable)
8044                 {
8045                         r_refdef.oldgl_fogenable = false;
8046                         r_refdef.fog_density = 0;
8047                         r_refdef.fog_red = 0;
8048                         r_refdef.fog_green = 0;
8049                         r_refdef.fog_blue = 0;
8050                         r_refdef.fog_alpha = 0;
8051                         r_refdef.fog_start = 0;
8052                         r_refdef.fog_end = 0;
8053                         r_refdef.fog_height = 1<<30;
8054                         r_refdef.fog_fadedepth = 128;
8055                 }
8056         }
8057
8058         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
8059         r_refdef.fog_start = max(0, r_refdef.fog_start);
8060         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
8061
8062         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
8063
8064         if (r_refdef.fog_density && r_drawfog.integer)
8065         {
8066                 r_refdef.fogenabled = true;
8067                 // this is the point where the fog reaches 0.9986 alpha, which we
8068                 // consider a good enough cutoff point for the texture
8069                 // (0.9986 * 256 == 255.6)
8070                 if (r_fog_exp2.integer)
8071                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
8072                 else
8073                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
8074                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
8075                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
8076                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
8077                 // fog color was already set
8078                 // update the fog texture
8079                 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)
8080                         R_BuildFogTexture();
8081         }
8082         else
8083                 r_refdef.fogenabled = false;
8084
8085         switch(vid.renderpath)
8086         {
8087         case RENDERPATH_GL20:
8088         case RENDERPATH_CGGL:
8089                 if(v_glslgamma.integer && !vid_gammatables_trivial)
8090                 {
8091                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
8092                         {
8093                                 // build GLSL gamma texture
8094 #define RAMPWIDTH 256
8095                                 unsigned short ramp[RAMPWIDTH * 3];
8096                                 unsigned char rampbgr[RAMPWIDTH][4];
8097                                 int i;
8098
8099                                 r_texture_gammaramps_serial = vid_gammatables_serial;
8100
8101                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
8102                                 for(i = 0; i < RAMPWIDTH; ++i)
8103                                 {
8104                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8105                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8106                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
8107                                         rampbgr[i][3] = 0;
8108                                 }
8109                                 if (r_texture_gammaramps)
8110                                 {
8111                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
8112                                 }
8113                                 else
8114                                 {
8115                                         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);
8116                                 }
8117                         }
8118                 }
8119                 else
8120                 {
8121                         // remove GLSL gamma texture
8122                 }
8123                 break;
8124         case RENDERPATH_GL13:
8125         case RENDERPATH_GL11:
8126                 break;
8127         }
8128 }
8129
8130 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
8131 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
8132 /*
8133 ================
8134 R_SelectScene
8135 ================
8136 */
8137 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
8138         if( scenetype != r_currentscenetype ) {
8139                 // store the old scenetype
8140                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
8141                 r_currentscenetype = scenetype;
8142                 // move in the new scene
8143                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
8144         }
8145 }
8146
8147 /*
8148 ================
8149 R_GetScenePointer
8150 ================
8151 */
8152 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
8153 {
8154         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
8155         if( scenetype == r_currentscenetype ) {
8156                 return &r_refdef.scene;
8157         } else {
8158                 return &r_scenes_store[ scenetype ];
8159         }
8160 }
8161
8162 /*
8163 ================
8164 R_RenderView
8165 ================
8166 */
8167 void R_RenderView(void)
8168 {
8169         if (r_timereport_active)
8170                 R_TimeReport("start");
8171         r_textureframe++; // used only by R_GetCurrentTexture
8172         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8173
8174         if (!r_drawentities.integer)
8175                 r_refdef.scene.numentities = 0;
8176
8177         R_AnimCache_ClearCache();
8178         R_FrameData_NewFrame();
8179
8180         if (r_refdef.view.isoverlay)
8181         {
8182                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
8183                 GL_Clear( GL_DEPTH_BUFFER_BIT );
8184                 R_TimeReport("depthclear");
8185
8186                 r_refdef.view.showdebug = false;
8187
8188                 r_waterstate.enabled = false;
8189                 r_waterstate.numwaterplanes = 0;
8190
8191                 R_RenderScene();
8192
8193                 CHECKGLERROR
8194                 return;
8195         }
8196
8197         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
8198                 return; //Host_Error ("R_RenderView: NULL worldmodel");
8199
8200         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
8201
8202         // break apart the view matrix into vectors for various purposes
8203         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8204         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8205         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8206         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8207         // make an inverted copy of the view matrix for tracking sprites
8208         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8209
8210         R_Shadow_UpdateWorldLightSelection();
8211
8212         R_Bloom_StartFrame();
8213         R_Water_StartFrame();
8214
8215         CHECKGLERROR
8216         if (r_timereport_active)
8217                 R_TimeReport("viewsetup");
8218
8219         R_ResetViewRendering3D();
8220
8221         if (r_refdef.view.clear || r_refdef.fogenabled)
8222         {
8223                 R_ClearScreen(r_refdef.fogenabled);
8224                 if (r_timereport_active)
8225                         R_TimeReport("viewclear");
8226         }
8227         r_refdef.view.clear = true;
8228
8229         // this produces a bloom texture to be used in R_BlendView() later
8230         if (r_hdr.integer && r_bloomstate.bloomwidth)
8231         {
8232                 R_HDR_RenderBloomTexture();
8233                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
8234                 r_textureframe++; // used only by R_GetCurrentTexture
8235         }
8236
8237         r_refdef.view.showdebug = true;
8238
8239         R_View_Update();
8240         if (r_timereport_active)
8241                 R_TimeReport("visibility");
8242
8243         r_waterstate.numwaterplanes = 0;
8244         if (r_waterstate.enabled)
8245                 R_RenderWaterPlanes();
8246
8247         R_RenderScene();
8248         r_waterstate.numwaterplanes = 0;
8249
8250         R_BlendView();
8251         if (r_timereport_active)
8252                 R_TimeReport("blendview");
8253
8254         GL_Scissor(0, 0, vid.width, vid.height);
8255         GL_ScissorTest(false);
8256         CHECKGLERROR
8257 }
8258
8259 void R_RenderWaterPlanes(void)
8260 {
8261         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
8262         {
8263                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
8264                 if (r_timereport_active)
8265                         R_TimeReport("waterworld");
8266         }
8267
8268         // don't let sound skip if going slow
8269         if (r_refdef.scene.extraupdate)
8270                 S_ExtraUpdate ();
8271
8272         R_DrawModelsAddWaterPlanes();
8273         if (r_timereport_active)
8274                 R_TimeReport("watermodels");
8275
8276         if (r_waterstate.numwaterplanes)
8277         {
8278                 R_Water_ProcessPlanes();
8279                 if (r_timereport_active)
8280                         R_TimeReport("waterscenes");
8281         }
8282 }
8283
8284 extern void R_DrawLightningBeams (void);
8285 extern void VM_CL_AddPolygonsToMeshQueue (void);
8286 extern void R_DrawPortals (void);
8287 extern cvar_t cl_locs_show;
8288 static void R_DrawLocs(void);
8289 static void R_DrawEntityBBoxes(void);
8290 static void R_DrawModelDecals(void);
8291 extern void R_DrawModelShadows(void);
8292 extern void R_DrawModelShadowMaps(void);
8293 extern cvar_t cl_decals_newsystem;
8294 extern qboolean r_shadow_usingdeferredprepass;
8295 void R_RenderScene(void)
8296 {
8297         qboolean shadowmapping = false;
8298
8299         r_refdef.stats.renders++;
8300
8301         R_UpdateFogColor();
8302
8303         // don't let sound skip if going slow
8304         if (r_refdef.scene.extraupdate)
8305                 S_ExtraUpdate ();
8306
8307         R_MeshQueue_BeginScene();
8308
8309         R_SkyStartFrame();
8310
8311         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);
8312
8313         if (cl.csqc_vidvars.drawworld)
8314         {
8315                 // don't let sound skip if going slow
8316                 if (r_refdef.scene.extraupdate)
8317                         S_ExtraUpdate ();
8318
8319                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
8320                 {
8321                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
8322                         if (r_timereport_active)
8323                                 R_TimeReport("worldsky");
8324                 }
8325
8326                 if (R_DrawBrushModelsSky() && r_timereport_active)
8327                         R_TimeReport("bmodelsky");
8328
8329                 if (skyrendermasked && skyrenderlater)
8330                 {
8331                         // we have to force off the water clipping plane while rendering sky
8332                         R_SetupView(false);
8333                         R_Sky();
8334                         R_SetupView(true);
8335                         if (r_timereport_active)
8336                                 R_TimeReport("sky");
8337                 }
8338         }
8339
8340         R_AnimCache_CacheVisibleEntities();
8341         if (r_timereport_active)
8342                 R_TimeReport("animation");
8343
8344         R_Shadow_PrepareLights();
8345         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
8346                 R_Shadow_PrepareModelShadows();
8347         if (r_timereport_active)
8348                 R_TimeReport("preparelights");
8349
8350         if (R_Shadow_ShadowMappingEnabled())
8351                 shadowmapping = true;
8352
8353         if (r_shadow_usingdeferredprepass)
8354                 R_Shadow_DrawPrepass();
8355
8356         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
8357         {
8358                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
8359                 if (r_timereport_active)
8360                         R_TimeReport("worlddepth");
8361         }
8362         if (r_depthfirst.integer >= 2)
8363         {
8364                 R_DrawModelsDepth();
8365                 if (r_timereport_active)
8366                         R_TimeReport("modeldepth");
8367         }
8368
8369         if (r_shadows.integer > 0 && shadowmapping && r_refdef.lightmapintensity > 0)
8370         {
8371                 R_DrawModelShadowMaps();
8372                 R_ResetViewRendering3D();
8373                 // don't let sound skip if going slow
8374                 if (r_refdef.scene.extraupdate)
8375                         S_ExtraUpdate ();
8376         }
8377
8378         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
8379         {
8380                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
8381                 if (r_timereport_active)
8382                         R_TimeReport("world");
8383         }
8384
8385         // don't let sound skip if going slow
8386         if (r_refdef.scene.extraupdate)
8387                 S_ExtraUpdate ();
8388
8389         R_DrawModels();
8390         if (r_timereport_active)
8391                 R_TimeReport("models");
8392
8393         // don't let sound skip if going slow
8394         if (r_refdef.scene.extraupdate)
8395                 S_ExtraUpdate ();
8396
8397         if (r_shadows.integer > 0 && !shadowmapping && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8398         {
8399                 R_DrawModelShadows();
8400                 R_ResetViewRendering3D();
8401                 // don't let sound skip if going slow
8402                 if (r_refdef.scene.extraupdate)
8403                         S_ExtraUpdate ();
8404         }
8405
8406         if (!r_shadow_usingdeferredprepass)
8407         {
8408                 R_Shadow_DrawLights();
8409                 if (r_timereport_active)
8410                         R_TimeReport("rtlights");
8411         }
8412
8413         // don't let sound skip if going slow
8414         if (r_refdef.scene.extraupdate)
8415                 S_ExtraUpdate ();
8416
8417         if (r_shadows.integer > 0 && !shadowmapping && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8418         {
8419                 R_DrawModelShadows();
8420                 R_ResetViewRendering3D();
8421                 // don't let sound skip if going slow
8422                 if (r_refdef.scene.extraupdate)
8423                         S_ExtraUpdate ();
8424         }
8425
8426         if (cl.csqc_vidvars.drawworld)
8427         {
8428                 if (cl_decals_newsystem.integer)
8429                 {
8430                         R_DrawModelDecals();
8431                         if (r_timereport_active)
8432                                 R_TimeReport("modeldecals");
8433                 }
8434                 else
8435                 {
8436                         R_DrawDecals();
8437                         if (r_timereport_active)
8438                                 R_TimeReport("decals");
8439                 }
8440
8441                 R_DrawParticles();
8442                 if (r_timereport_active)
8443                         R_TimeReport("particles");
8444
8445                 R_DrawExplosions();
8446                 if (r_timereport_active)
8447                         R_TimeReport("explosions");
8448
8449                 R_DrawLightningBeams();
8450                 if (r_timereport_active)
8451                         R_TimeReport("lightning");
8452         }
8453
8454         VM_CL_AddPolygonsToMeshQueue();
8455
8456         if (r_refdef.view.showdebug)
8457         {
8458                 if (cl_locs_show.integer)
8459                 {
8460                         R_DrawLocs();
8461                         if (r_timereport_active)
8462                                 R_TimeReport("showlocs");
8463                 }
8464
8465                 if (r_drawportals.integer)
8466                 {
8467                         R_DrawPortals();
8468                         if (r_timereport_active)
8469                                 R_TimeReport("portals");
8470                 }
8471
8472                 if (r_showbboxes.value > 0)
8473                 {
8474                         R_DrawEntityBBoxes();
8475                         if (r_timereport_active)
8476                                 R_TimeReport("bboxes");
8477                 }
8478         }
8479
8480         R_MeshQueue_RenderTransparent();
8481         if (r_timereport_active)
8482                 R_TimeReport("drawtrans");
8483
8484         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))
8485         {
8486                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
8487                 if (r_timereport_active)
8488                         R_TimeReport("worlddebug");
8489                 R_DrawModelsDebug();
8490                 if (r_timereport_active)
8491                         R_TimeReport("modeldebug");
8492         }
8493
8494         if (cl.csqc_vidvars.drawworld)
8495         {
8496                 R_Shadow_DrawCoronas();
8497                 if (r_timereport_active)
8498                         R_TimeReport("coronas");
8499         }
8500
8501         // don't let sound skip if going slow
8502         if (r_refdef.scene.extraupdate)
8503                 S_ExtraUpdate ();
8504
8505         R_ResetViewRendering2D();
8506 }
8507
8508 static const unsigned short bboxelements[36] =
8509 {
8510         5, 1, 3, 5, 3, 7,
8511         6, 2, 0, 6, 0, 4,
8512         7, 3, 2, 7, 2, 6,
8513         4, 0, 1, 4, 1, 5,
8514         4, 5, 7, 4, 7, 6,
8515         1, 0, 2, 1, 2, 3,
8516 };
8517
8518 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
8519 {
8520         int i;
8521         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
8522
8523         RSurf_ActiveWorldEntity();
8524
8525         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8526         GL_DepthMask(false);
8527         GL_DepthRange(0, 1);
8528         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8529         R_Mesh_ResetTextureState();
8530
8531         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
8532         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
8533         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
8534         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
8535         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
8536         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
8537         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
8538         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
8539         R_FillColors(color4f, 8, cr, cg, cb, ca);
8540         if (r_refdef.fogenabled)
8541         {
8542                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
8543                 {
8544                         f1 = RSurf_FogVertex(v);
8545                         f2 = 1 - f1;
8546                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
8547                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
8548                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
8549                 }
8550         }
8551         R_Mesh_VertexPointer(vertex3f, 0, 0);
8552         R_Mesh_ColorPointer(color4f, 0, 0);
8553         R_Mesh_ResetTextureState();
8554         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8555         R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
8556 }
8557
8558 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8559 {
8560         int i;
8561         float color[4];
8562         prvm_edict_t *edict;
8563         prvm_prog_t *prog_save = prog;
8564
8565         // this function draws bounding boxes of server entities
8566         if (!sv.active)
8567                 return;
8568
8569         GL_CullFace(GL_NONE);
8570         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8571
8572         prog = 0;
8573         SV_VM_Begin();
8574         for (i = 0;i < numsurfaces;i++)
8575         {
8576                 edict = PRVM_EDICT_NUM(surfacelist[i]);
8577                 switch ((int)edict->fields.server->solid)
8578                 {
8579                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
8580                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
8581                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
8582                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
8583                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
8584                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
8585                 }
8586                 color[3] *= r_showbboxes.value;
8587                 color[3] = bound(0, color[3], 1);
8588                 GL_DepthTest(!r_showdisabledepthtest.integer);
8589                 GL_CullFace(r_refdef.view.cullface_front);
8590                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
8591         }
8592         SV_VM_End();
8593         prog = prog_save;
8594 }
8595
8596 static void R_DrawEntityBBoxes(void)
8597 {
8598         int i;
8599         prvm_edict_t *edict;
8600         vec3_t center;
8601         prvm_prog_t *prog_save = prog;
8602
8603         // this function draws bounding boxes of server entities
8604         if (!sv.active)
8605                 return;
8606
8607         prog = 0;
8608         SV_VM_Begin();
8609         for (i = 0;i < prog->num_edicts;i++)
8610         {
8611                 edict = PRVM_EDICT_NUM(i);
8612                 if (edict->priv.server->free)
8613                         continue;
8614                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
8615                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
8616                         continue;
8617                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
8618                         continue;
8619                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
8620                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
8621         }
8622         SV_VM_End();
8623         prog = prog_save;
8624 }
8625
8626 static const int nomodelelement3i[24] =
8627 {
8628         5, 2, 0,
8629         5, 1, 2,
8630         5, 0, 3,
8631         5, 3, 1,
8632         0, 2, 4,
8633         2, 1, 4,
8634         3, 0, 4,
8635         1, 3, 4
8636 };
8637
8638 static const unsigned short nomodelelement3s[24] =
8639 {
8640         5, 2, 0,
8641         5, 1, 2,
8642         5, 0, 3,
8643         5, 3, 1,
8644         0, 2, 4,
8645         2, 1, 4,
8646         3, 0, 4,
8647         1, 3, 4
8648 };
8649
8650 static const float nomodelvertex3f[6*3] =
8651 {
8652         -16,   0,   0,
8653          16,   0,   0,
8654           0, -16,   0,
8655           0,  16,   0,
8656           0,   0, -16,
8657           0,   0,  16
8658 };
8659
8660 static const float nomodelcolor4f[6*4] =
8661 {
8662         0.0f, 0.0f, 0.5f, 1.0f,
8663         0.0f, 0.0f, 0.5f, 1.0f,
8664         0.0f, 0.5f, 0.0f, 1.0f,
8665         0.0f, 0.5f, 0.0f, 1.0f,
8666         0.5f, 0.0f, 0.0f, 1.0f,
8667         0.5f, 0.0f, 0.0f, 1.0f
8668 };
8669
8670 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8671 {
8672         int i;
8673         float f1, f2, *c;
8674         float color4f[6*4];
8675
8676         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);
8677
8678         // this is only called once per entity so numsurfaces is always 1, and
8679         // surfacelist is always {0}, so this code does not handle batches
8680
8681         if (rsurface.ent_flags & RENDER_ADDITIVE)
8682         {
8683                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
8684                 GL_DepthMask(false);
8685         }
8686         else if (rsurface.colormod[3] < 1)
8687         {
8688                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8689                 GL_DepthMask(false);
8690         }
8691         else
8692         {
8693                 GL_BlendFunc(GL_ONE, GL_ZERO);
8694                 GL_DepthMask(true);
8695         }
8696         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8697         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8698         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8699         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8700         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8701         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
8702         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8703         R_Mesh_ColorPointer(color4f, 0, 0);
8704         for (i = 0, c = color4f;i < 6;i++, c += 4)
8705         {
8706                 c[0] *= rsurface.colormod[0];
8707                 c[1] *= rsurface.colormod[1];
8708                 c[2] *= rsurface.colormod[2];
8709                 c[3] *= rsurface.colormod[3];
8710         }
8711         if (r_refdef.fogenabled)
8712         {
8713                 for (i = 0, c = color4f;i < 6;i++, c += 4)
8714                 {
8715                         f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
8716                         f2 = 1 - f1;
8717                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8718                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8719                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8720                 }
8721         }
8722         R_Mesh_ResetTextureState();
8723         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
8724 }
8725
8726 void R_DrawNoModel(entity_render_t *ent)
8727 {
8728         vec3_t org;
8729         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8730         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8731                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8732         else
8733                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8734 }
8735
8736 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8737 {
8738         vec3_t right1, right2, diff, normal;
8739
8740         VectorSubtract (org2, org1, normal);
8741
8742         // calculate 'right' vector for start
8743         VectorSubtract (r_refdef.view.origin, org1, diff);
8744         CrossProduct (normal, diff, right1);
8745         VectorNormalize (right1);
8746
8747         // calculate 'right' vector for end
8748         VectorSubtract (r_refdef.view.origin, org2, diff);
8749         CrossProduct (normal, diff, right2);
8750         VectorNormalize (right2);
8751
8752         vert[ 0] = org1[0] + width * right1[0];
8753         vert[ 1] = org1[1] + width * right1[1];
8754         vert[ 2] = org1[2] + width * right1[2];
8755         vert[ 3] = org1[0] - width * right1[0];
8756         vert[ 4] = org1[1] - width * right1[1];
8757         vert[ 5] = org1[2] - width * right1[2];
8758         vert[ 6] = org2[0] - width * right2[0];
8759         vert[ 7] = org2[1] - width * right2[1];
8760         vert[ 8] = org2[2] - width * right2[2];
8761         vert[ 9] = org2[0] + width * right2[0];
8762         vert[10] = org2[1] + width * right2[1];
8763         vert[11] = org2[2] + width * right2[2];
8764 }
8765
8766 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)
8767 {
8768         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8769         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8770         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8771         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8772         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8773         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8774         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8775         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8776         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8777         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8778         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8779         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8780 }
8781
8782 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8783 {
8784         int i;
8785         float *vertex3f;
8786         float v[3];
8787         VectorSet(v, x, y, z);
8788         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8789                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8790                         break;
8791         if (i == mesh->numvertices)
8792         {
8793                 if (mesh->numvertices < mesh->maxvertices)
8794                 {
8795                         VectorCopy(v, vertex3f);
8796                         mesh->numvertices++;
8797                 }
8798                 return mesh->numvertices;
8799         }
8800         else
8801                 return i;
8802 }
8803
8804 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8805 {
8806         int i;
8807         int *e, element[3];
8808         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8809         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8810         e = mesh->element3i + mesh->numtriangles * 3;
8811         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8812         {
8813                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8814                 if (mesh->numtriangles < mesh->maxtriangles)
8815                 {
8816                         *e++ = element[0];
8817                         *e++ = element[1];
8818                         *e++ = element[2];
8819                         mesh->numtriangles++;
8820                 }
8821                 element[1] = element[2];
8822         }
8823 }
8824
8825 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8826 {
8827         int i;
8828         int *e, element[3];
8829         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8830         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8831         e = mesh->element3i + mesh->numtriangles * 3;
8832         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8833         {
8834                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8835                 if (mesh->numtriangles < mesh->maxtriangles)
8836                 {
8837                         *e++ = element[0];
8838                         *e++ = element[1];
8839                         *e++ = element[2];
8840                         mesh->numtriangles++;
8841                 }
8842                 element[1] = element[2];
8843         }
8844 }
8845
8846 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8847 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8848 {
8849         int planenum, planenum2;
8850         int w;
8851         int tempnumpoints;
8852         mplane_t *plane, *plane2;
8853         double maxdist;
8854         double temppoints[2][256*3];
8855         // figure out how large a bounding box we need to properly compute this brush
8856         maxdist = 0;
8857         for (w = 0;w < numplanes;w++)
8858                 maxdist = max(maxdist, fabs(planes[w].dist));
8859         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8860         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8861         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8862         {
8863                 w = 0;
8864                 tempnumpoints = 4;
8865                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8866                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8867                 {
8868                         if (planenum2 == planenum)
8869                                 continue;
8870                         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);
8871                         w = !w;
8872                 }
8873                 if (tempnumpoints < 3)
8874                         continue;
8875                 // generate elements forming a triangle fan for this polygon
8876                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8877         }
8878 }
8879
8880 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)
8881 {
8882         texturelayer_t *layer;
8883         layer = t->currentlayers + t->currentnumlayers++;
8884         layer->type = type;
8885         layer->depthmask = depthmask;
8886         layer->blendfunc1 = blendfunc1;
8887         layer->blendfunc2 = blendfunc2;
8888         layer->texture = texture;
8889         layer->texmatrix = *matrix;
8890         layer->color[0] = r;
8891         layer->color[1] = g;
8892         layer->color[2] = b;
8893         layer->color[3] = a;
8894 }
8895
8896 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8897 {
8898         double index, f;
8899         index = parms[2] + r_refdef.scene.time * parms[3];
8900         index -= floor(index);
8901         switch (func)
8902         {
8903         default:
8904         case Q3WAVEFUNC_NONE:
8905         case Q3WAVEFUNC_NOISE:
8906         case Q3WAVEFUNC_COUNT:
8907                 f = 0;
8908                 break;
8909         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8910         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8911         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8912         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8913         case Q3WAVEFUNC_TRIANGLE:
8914                 index *= 4;
8915                 f = index - floor(index);
8916                 if (index < 1)
8917                         f = f;
8918                 else if (index < 2)
8919                         f = 1 - f;
8920                 else if (index < 3)
8921                         f = -f;
8922                 else
8923                         f = -(1 - f);
8924                 break;
8925         }
8926         return (float)(parms[0] + parms[1] * f);
8927 }
8928
8929 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8930 {
8931         int w, h, idx;
8932         float f;
8933         float tcmat[12];
8934         matrix4x4_t matrix, temp;
8935         switch(tcmod->tcmod)
8936         {
8937                 case Q3TCMOD_COUNT:
8938                 case Q3TCMOD_NONE:
8939                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8940                                 matrix = r_waterscrollmatrix;
8941                         else
8942                                 matrix = identitymatrix;
8943                         break;
8944                 case Q3TCMOD_ENTITYTRANSLATE:
8945                         // this is used in Q3 to allow the gamecode to control texcoord
8946                         // scrolling on the entity, which is not supported in darkplaces yet.
8947                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8948                         break;
8949                 case Q3TCMOD_ROTATE:
8950                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8951                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
8952                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8953                         break;
8954                 case Q3TCMOD_SCALE:
8955                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8956                         break;
8957                 case Q3TCMOD_SCROLL:
8958                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
8959                         break;
8960                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8961                         w = (int) tcmod->parms[0];
8962                         h = (int) tcmod->parms[1];
8963                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
8964                         f = f - floor(f);
8965                         idx = (int) floor(f * w * h);
8966                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8967                         break;
8968                 case Q3TCMOD_STRETCH:
8969                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8970                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8971                         break;
8972                 case Q3TCMOD_TRANSFORM:
8973                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8974                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8975                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8976                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8977                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8978                         break;
8979                 case Q3TCMOD_TURBULENT:
8980                         // this is handled in the RSurf_PrepareVertices function
8981                         matrix = identitymatrix;
8982                         break;
8983         }
8984         temp = *texmatrix;
8985         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8986 }
8987
8988 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8989 {
8990         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
8991         char name[MAX_QPATH];
8992         skinframe_t *skinframe;
8993         unsigned char pixels[296*194];
8994         strlcpy(cache->name, skinname, sizeof(cache->name));
8995         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8996         if (developer_loading.integer)
8997                 Con_Printf("loading %s\n", name);
8998         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8999         if (!skinframe || !skinframe->base)
9000         {
9001                 unsigned char *f;
9002                 fs_offset_t filesize;
9003                 skinframe = NULL;
9004                 f = FS_LoadFile(name, tempmempool, true, &filesize);
9005                 if (f)
9006                 {
9007                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
9008                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
9009                         Mem_Free(f);
9010                 }
9011         }
9012         cache->skinframe = skinframe;
9013 }
9014
9015 texture_t *R_GetCurrentTexture(texture_t *t)
9016 {
9017         int i;
9018         const entity_render_t *ent = rsurface.entity;
9019         dp_model_t *model = ent->model;
9020         q3shaderinfo_layer_tcmod_t *tcmod;
9021
9022         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
9023                 return t->currentframe;
9024         t->update_lastrenderframe = r_textureframe;
9025         t->update_lastrenderentity = (void *)ent;
9026
9027         // switch to an alternate material if this is a q1bsp animated material
9028         {
9029                 texture_t *texture = t;
9030                 int s = rsurface.ent_skinnum;
9031                 if ((unsigned int)s >= (unsigned int)model->numskins)
9032                         s = 0;
9033                 if (model->skinscenes)
9034                 {
9035                         if (model->skinscenes[s].framecount > 1)
9036                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
9037                         else
9038                                 s = model->skinscenes[s].firstframe;
9039                 }
9040                 if (s > 0)
9041                         t = t + s * model->num_surfaces;
9042                 if (t->animated)
9043                 {
9044                         // use an alternate animation if the entity's frame is not 0,
9045                         // and only if the texture has an alternate animation
9046                         if (rsurface.ent_alttextures && t->anim_total[1])
9047                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
9048                         else
9049                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
9050                 }
9051                 texture->currentframe = t;
9052         }
9053
9054         // update currentskinframe to be a qw skin or animation frame
9055         if (rsurface.ent_qwskin >= 0)
9056         {
9057                 i = rsurface.ent_qwskin;
9058                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
9059                 {
9060                         r_qwskincache_size = cl.maxclients;
9061                         if (r_qwskincache)
9062                                 Mem_Free(r_qwskincache);
9063                         r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
9064                 }
9065                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
9066                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
9067                 t->currentskinframe = r_qwskincache[i].skinframe;
9068                 if (t->currentskinframe == NULL)
9069                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9070         }
9071         else if (t->numskinframes >= 2)
9072                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9073         if (t->backgroundnumskinframes >= 2)
9074                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
9075
9076         t->currentmaterialflags = t->basematerialflags;
9077         t->currentalpha = rsurface.colormod[3];
9078         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
9079                 t->currentalpha *= r_wateralpha.value;
9080         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
9081                 t->currentalpha *= t->r_water_wateralpha;
9082         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
9083                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
9084         if (!(rsurface.ent_flags & RENDER_LIGHT))
9085                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
9086         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
9087         {
9088                 // pick a model lighting mode
9089                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
9090                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
9091                 else
9092                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
9093         }
9094         if (rsurface.ent_flags & RENDER_ADDITIVE)
9095                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9096         else if (t->currentalpha < 1)
9097                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9098         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
9099                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
9100         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
9101                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
9102         if (t->backgroundnumskinframes)
9103                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
9104         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
9105         {
9106                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
9107                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
9108         }
9109         else
9110                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
9111         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
9112                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
9113
9114         // there is no tcmod
9115         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9116         {
9117                 t->currenttexmatrix = r_waterscrollmatrix;
9118                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
9119         }
9120         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
9121         {
9122                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
9123                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
9124         }
9125
9126         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9127                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
9128         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9129                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
9130
9131         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
9132         if (t->currentskinframe->qpixels)
9133                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
9134         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
9135         if (!t->basetexture)
9136                 t->basetexture = r_texture_notexture;
9137         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
9138         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
9139         t->nmaptexture = t->currentskinframe->nmap;
9140         if (!t->nmaptexture)
9141                 t->nmaptexture = r_texture_blanknormalmap;
9142         t->glosstexture = r_texture_black;
9143         t->glowtexture = t->currentskinframe->glow;
9144         t->fogtexture = t->currentskinframe->fog;
9145         t->reflectmasktexture = t->currentskinframe->reflect;
9146         if (t->backgroundnumskinframes)
9147         {
9148                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
9149                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
9150                 t->backgroundglosstexture = r_texture_black;
9151                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
9152                 if (!t->backgroundnmaptexture)
9153                         t->backgroundnmaptexture = r_texture_blanknormalmap;
9154         }
9155         else
9156         {
9157                 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
9158                 t->backgroundnmaptexture = r_texture_blanknormalmap;
9159                 t->backgroundglosstexture = r_texture_black;
9160                 t->backgroundglowtexture = NULL;
9161         }
9162         t->specularpower = r_shadow_glossexponent.value;
9163         // TODO: store reference values for these in the texture?
9164         t->specularscale = 0;
9165         if (r_shadow_gloss.integer > 0)
9166         {
9167                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
9168                 {
9169                         if (r_shadow_glossintensity.value > 0)
9170                         {
9171                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
9172                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
9173                                 t->specularscale = r_shadow_glossintensity.value;
9174                         }
9175                 }
9176                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
9177                 {
9178                         t->glosstexture = r_texture_white;
9179                         t->backgroundglosstexture = r_texture_white;
9180                         t->specularscale = r_shadow_gloss2intensity.value;
9181                         t->specularpower = r_shadow_gloss2exponent.value;
9182                 }
9183         }
9184         t->specularscale *= t->specularscalemod;
9185         t->specularpower *= t->specularpowermod;
9186
9187         // lightmaps mode looks bad with dlights using actual texturing, so turn
9188         // off the colormap and glossmap, but leave the normalmap on as it still
9189         // accurately represents the shading involved
9190         if (gl_lightmaps.integer)
9191         {
9192                 t->basetexture = r_texture_grey128;
9193                 t->pantstexture = r_texture_black;
9194                 t->shirttexture = r_texture_black;
9195                 t->nmaptexture = r_texture_blanknormalmap;
9196                 t->glosstexture = r_texture_black;
9197                 t->glowtexture = NULL;
9198                 t->fogtexture = NULL;
9199                 t->reflectmasktexture = NULL;
9200                 t->backgroundbasetexture = NULL;
9201                 t->backgroundnmaptexture = r_texture_blanknormalmap;
9202                 t->backgroundglosstexture = r_texture_black;
9203                 t->backgroundglowtexture = NULL;
9204                 t->specularscale = 0;
9205                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
9206         }
9207
9208         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
9209         VectorClear(t->dlightcolor);
9210         t->currentnumlayers = 0;
9211         if (t->currentmaterialflags & MATERIALFLAG_WALL)
9212         {
9213                 int blendfunc1, blendfunc2;
9214                 qboolean depthmask;
9215                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
9216                 {
9217                         blendfunc1 = GL_SRC_ALPHA;
9218                         blendfunc2 = GL_ONE;
9219                 }
9220                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
9221                 {
9222                         blendfunc1 = GL_SRC_ALPHA;
9223                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
9224                 }
9225                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9226                 {
9227                         blendfunc1 = t->customblendfunc[0];
9228                         blendfunc2 = t->customblendfunc[1];
9229                 }
9230                 else
9231                 {
9232                         blendfunc1 = GL_ONE;
9233                         blendfunc2 = GL_ZERO;
9234                 }
9235                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
9236                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9237                 {
9238                         // fullbright is not affected by r_refdef.lightmapintensity
9239                         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]);
9240                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9241                                 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]);
9242                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9243                                 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]);
9244                 }
9245                 else
9246                 {
9247                         vec3_t ambientcolor;
9248                         float colorscale;
9249                         // set the color tint used for lights affecting this surface
9250                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
9251                         colorscale = 2;
9252                         // q3bsp has no lightmap updates, so the lightstylevalue that
9253                         // would normally be baked into the lightmap must be
9254                         // applied to the color
9255                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
9256                         if (model->type == mod_brushq3)
9257                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
9258                         colorscale *= r_refdef.lightmapintensity;
9259                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
9260                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
9261                         // basic lit geometry
9262                         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]);
9263                         // add pants/shirt if needed
9264                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9265                                 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]);
9266                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9267                                 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]);
9268                         // now add ambient passes if needed
9269                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
9270                         {
9271                                 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]);
9272                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9273                                         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]);
9274                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9275                                         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]);
9276                         }
9277                 }
9278                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
9279                         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]);
9280                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
9281                 {
9282                         // if this is opaque use alpha blend which will darken the earlier
9283                         // passes cheaply.
9284                         //
9285                         // if this is an alpha blended material, all the earlier passes
9286                         // were darkened by fog already, so we only need to add the fog
9287                         // color ontop through the fog mask texture
9288                         //
9289                         // if this is an additive blended material, all the earlier passes
9290                         // were darkened by fog already, and we should not add fog color
9291                         // (because the background was not darkened, there is no fog color
9292                         // that was lost behind it).
9293                         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]);
9294                 }
9295         }
9296
9297         return t->currentframe;
9298 }
9299
9300 rsurfacestate_t rsurface;
9301
9302 void R_Mesh_ResizeArrays(int newvertices)
9303 {
9304         float *base;
9305         if (rsurface.array_size >= newvertices)
9306                 return;
9307         if (rsurface.array_modelvertex3f)
9308                 Mem_Free(rsurface.array_modelvertex3f);
9309         rsurface.array_size = (newvertices + 1023) & ~1023;
9310         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
9311         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
9312         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
9313         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
9314         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
9315         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
9316         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
9317         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
9318         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
9319         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
9320         rsurface.array_color4f           = base + rsurface.array_size * 27;
9321         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
9322 }
9323
9324 void RSurf_ActiveWorldEntity(void)
9325 {
9326         dp_model_t *model = r_refdef.scene.worldmodel;
9327         //if (rsurface.entity == r_refdef.scene.worldentity)
9328         //      return;
9329         rsurface.entity = r_refdef.scene.worldentity;
9330         rsurface.skeleton = NULL;
9331         rsurface.ent_skinnum = 0;
9332         rsurface.ent_qwskin = -1;
9333         rsurface.ent_shadertime = 0;
9334         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
9335         if (rsurface.array_size < model->surfmesh.num_vertices)
9336                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9337         rsurface.matrix = identitymatrix;
9338         rsurface.inversematrix = identitymatrix;
9339         rsurface.matrixscale = 1;
9340         rsurface.inversematrixscale = 1;
9341         R_EntityMatrix(&identitymatrix);
9342         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
9343         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
9344         rsurface.fograngerecip = r_refdef.fograngerecip;
9345         rsurface.fogheightfade = r_refdef.fogheightfade;
9346         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
9347         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9348         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9349         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9350         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9351         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9352         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9353         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
9354         rsurface.colormod[3] = 1;
9355         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);
9356         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9357         rsurface.frameblend[0].lerp = 1;
9358         rsurface.ent_alttextures = false;
9359         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9360         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9361         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
9362         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9363         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9364         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9365         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9366         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9367         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9368         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9369         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9370         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
9371         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9372         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9373         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
9374         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9375         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9376         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
9377         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9378         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9379         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
9380         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9381         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9382         rsurface.modelelement3i = model->surfmesh.data_element3i;
9383         rsurface.modelelement3s = model->surfmesh.data_element3s;
9384         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9385         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9386         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9387         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9388         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9389         rsurface.modelsurfaces = model->data_surfaces;
9390         rsurface.generatedvertex = false;
9391         rsurface.vertex3f  = rsurface.modelvertex3f;
9392         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9393         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9394         rsurface.svector3f = rsurface.modelsvector3f;
9395         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9396         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9397         rsurface.tvector3f = rsurface.modeltvector3f;
9398         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9399         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9400         rsurface.normal3f  = rsurface.modelnormal3f;
9401         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9402         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9403         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9404 }
9405
9406 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
9407 {
9408         dp_model_t *model = ent->model;
9409         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
9410         //      return;
9411         rsurface.entity = (entity_render_t *)ent;
9412         rsurface.skeleton = ent->skeleton;
9413         rsurface.ent_skinnum = ent->skinnum;
9414         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;
9415         rsurface.ent_shadertime = ent->shadertime;
9416         rsurface.ent_flags = ent->flags;
9417         if (rsurface.array_size < model->surfmesh.num_vertices)
9418                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9419         rsurface.matrix = ent->matrix;
9420         rsurface.inversematrix = ent->inversematrix;
9421         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9422         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9423         R_EntityMatrix(&rsurface.matrix);
9424         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9425         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9426         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9427         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9428         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9429         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9430         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
9431         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
9432         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
9433         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
9434         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
9435         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
9436         rsurface.colormod[3] = ent->alpha;
9437         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
9438         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
9439         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
9440         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9441         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9442         if (ent->model->brush.submodel && !prepass)
9443         {
9444                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
9445                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
9446         }
9447         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
9448         {
9449                 if (ent->animcache_vertex3f && !r_framedata_failed)
9450                 {
9451                         rsurface.modelvertex3f = ent->animcache_vertex3f;
9452                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
9453                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
9454                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
9455                 }
9456                 else if (wanttangents)
9457                 {
9458                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9459                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9460                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9461                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9462                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
9463                 }
9464                 else if (wantnormals)
9465                 {
9466                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9467                         rsurface.modelsvector3f = NULL;
9468                         rsurface.modeltvector3f = NULL;
9469                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9470                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
9471                 }
9472                 else
9473                 {
9474                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9475                         rsurface.modelsvector3f = NULL;
9476                         rsurface.modeltvector3f = NULL;
9477                         rsurface.modelnormal3f = NULL;
9478                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
9479                 }
9480                 rsurface.modelvertex3f_bufferobject = 0;
9481                 rsurface.modelvertex3f_bufferoffset = 0;
9482                 rsurface.modelsvector3f_bufferobject = 0;
9483                 rsurface.modelsvector3f_bufferoffset = 0;
9484                 rsurface.modeltvector3f_bufferobject = 0;
9485                 rsurface.modeltvector3f_bufferoffset = 0;
9486                 rsurface.modelnormal3f_bufferobject = 0;
9487                 rsurface.modelnormal3f_bufferoffset = 0;
9488                 rsurface.generatedvertex = true;
9489         }
9490         else
9491         {
9492                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
9493                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9494                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9495                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9496                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9497                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9498                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9499                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9500                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9501                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
9502                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9503                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9504                 rsurface.generatedvertex = false;
9505         }
9506         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
9507         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9508         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9509         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
9510         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9511         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9512         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
9513         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9514         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9515         rsurface.modelelement3i = model->surfmesh.data_element3i;
9516         rsurface.modelelement3s = model->surfmesh.data_element3s;
9517         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9518         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9519         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9520         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9521         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9522         rsurface.modelsurfaces = model->data_surfaces;
9523         rsurface.vertex3f  = rsurface.modelvertex3f;
9524         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9525         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9526         rsurface.svector3f = rsurface.modelsvector3f;
9527         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9528         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9529         rsurface.tvector3f = rsurface.modeltvector3f;
9530         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9531         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9532         rsurface.normal3f  = rsurface.modelnormal3f;
9533         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9534         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9535         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9536 }
9537
9538 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)
9539 {
9540         rsurface.entity = r_refdef.scene.worldentity;
9541         rsurface.skeleton = NULL;
9542         rsurface.ent_skinnum = 0;
9543         rsurface.ent_qwskin = -1;
9544         rsurface.ent_shadertime = shadertime;
9545         rsurface.ent_flags = entflags;
9546         rsurface.modelnum_vertices = numvertices;
9547         rsurface.modelnum_triangles = numtriangles;
9548         if (rsurface.array_size < rsurface.modelnum_vertices)
9549                 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
9550         rsurface.matrix = *matrix;
9551         rsurface.inversematrix = *inversematrix;
9552         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9553         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9554         R_EntityMatrix(&rsurface.matrix);
9555         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9556         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9557         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9558         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9559         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9560         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9561         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9562         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9563         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9564         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9565         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9566         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
9567         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);
9568         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9569         rsurface.frameblend[0].lerp = 1;
9570         rsurface.ent_alttextures = false;
9571         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9572         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9573         if (wanttangents)
9574         {
9575                 rsurface.modelvertex3f = vertex3f;
9576                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
9577                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
9578                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9579         }
9580         else if (wantnormals)
9581         {
9582                 rsurface.modelvertex3f = vertex3f;
9583                 rsurface.modelsvector3f = NULL;
9584                 rsurface.modeltvector3f = NULL;
9585                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9586         }
9587         else
9588         {
9589                 rsurface.modelvertex3f = vertex3f;
9590                 rsurface.modelsvector3f = NULL;
9591                 rsurface.modeltvector3f = NULL;
9592                 rsurface.modelnormal3f = NULL;
9593         }
9594         rsurface.modelvertex3f_bufferobject = 0;
9595         rsurface.modelvertex3f_bufferoffset = 0;
9596         rsurface.modelsvector3f_bufferobject = 0;
9597         rsurface.modelsvector3f_bufferoffset = 0;
9598         rsurface.modeltvector3f_bufferobject = 0;
9599         rsurface.modeltvector3f_bufferoffset = 0;
9600         rsurface.modelnormal3f_bufferobject = 0;
9601         rsurface.modelnormal3f_bufferoffset = 0;
9602         rsurface.generatedvertex = true;
9603         rsurface.modellightmapcolor4f  = color4f;
9604         rsurface.modellightmapcolor4f_bufferobject = 0;
9605         rsurface.modellightmapcolor4f_bufferoffset = 0;
9606         rsurface.modeltexcoordtexture2f  = texcoord2f;
9607         rsurface.modeltexcoordtexture2f_bufferobject = 0;
9608         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9609         rsurface.modeltexcoordlightmap2f  = NULL;
9610         rsurface.modeltexcoordlightmap2f_bufferobject = 0;
9611         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9612         rsurface.modelelement3i = element3i;
9613         rsurface.modelelement3s = element3s;
9614         rsurface.modelelement3i_bufferobject = 0;
9615         rsurface.modelelement3s_bufferobject = 0;
9616         rsurface.modellightmapoffsets = NULL;
9617         rsurface.modelsurfaces = NULL;
9618         rsurface.vertex3f  = rsurface.modelvertex3f;
9619         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9620         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9621         rsurface.svector3f = rsurface.modelsvector3f;
9622         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9623         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9624         rsurface.tvector3f = rsurface.modeltvector3f;
9625         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9626         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9627         rsurface.normal3f  = rsurface.modelnormal3f;
9628         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9629         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9630         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9631
9632         if (rsurface.modelnum_vertices && rsurface.modelelement3i)
9633         {
9634                 if ((wantnormals || wanttangents) && !normal3f)
9635                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9636                 if (wanttangents && !svector3f)
9637                         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);
9638         }
9639 }
9640
9641 float RSurf_FogPoint(const float *v)
9642 {
9643         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9644         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9645         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9646         float FogHeightFade = r_refdef.fogheightfade;
9647         float fogfrac;
9648         unsigned int fogmasktableindex;
9649         if (r_refdef.fogplaneviewabove)
9650                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9651         else
9652                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9653         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9654         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9655 }
9656
9657 float RSurf_FogVertex(const float *v)
9658 {
9659         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9660         float FogPlaneViewDist = rsurface.fogplaneviewdist;
9661         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9662         float FogHeightFade = rsurface.fogheightfade;
9663         float fogfrac;
9664         unsigned int fogmasktableindex;
9665         if (r_refdef.fogplaneviewabove)
9666                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9667         else
9668                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9669         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9670         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9671 }
9672
9673 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9674 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9675 {
9676         int deformindex;
9677         int texturesurfaceindex;
9678         int i, j;
9679         float amplitude;
9680         float animpos;
9681         float scale;
9682         const float *v1, *in_tc;
9683         float *out_tc;
9684         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9685         float waveparms[4];
9686         q3shaderinfo_deform_t *deform;
9687         // 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
9688         if (rsurface.generatedvertex)
9689         {
9690                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
9691                         generatenormals = true;
9692                 for (i = 0;i < Q3MAXDEFORMS;i++)
9693                 {
9694                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
9695                         {
9696                                 generatetangents = true;
9697                                 generatenormals = true;
9698                         }
9699                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
9700                                 generatenormals = true;
9701                 }
9702                 if (generatenormals && !rsurface.modelnormal3f)
9703                 {
9704                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9705                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
9706                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
9707                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9708                 }
9709                 if (generatetangents && !rsurface.modelsvector3f)
9710                 {
9711                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9712                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
9713                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
9714                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9715                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
9716                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
9717                         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);
9718                 }
9719         }
9720         rsurface.vertex3f  = rsurface.modelvertex3f;
9721         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9722         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9723         rsurface.svector3f = rsurface.modelsvector3f;
9724         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9725         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9726         rsurface.tvector3f = rsurface.modeltvector3f;
9727         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9728         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9729         rsurface.normal3f  = rsurface.modelnormal3f;
9730         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9731         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9732         // if vertices are deformed (sprite flares and things in maps, possibly
9733         // water waves, bulges and other deformations), generate them into
9734         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
9735         // (may be static model data or generated data for an animated model, or
9736         //  the previous deform pass)
9737         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
9738         {
9739                 switch (deform->deform)
9740                 {
9741                 default:
9742                 case Q3DEFORM_PROJECTIONSHADOW:
9743                 case Q3DEFORM_TEXT0:
9744                 case Q3DEFORM_TEXT1:
9745                 case Q3DEFORM_TEXT2:
9746                 case Q3DEFORM_TEXT3:
9747                 case Q3DEFORM_TEXT4:
9748                 case Q3DEFORM_TEXT5:
9749                 case Q3DEFORM_TEXT6:
9750                 case Q3DEFORM_TEXT7:
9751                 case Q3DEFORM_NONE:
9752                         break;
9753                 case Q3DEFORM_AUTOSPRITE:
9754                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9755                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9756                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9757                         VectorNormalize(newforward);
9758                         VectorNormalize(newright);
9759                         VectorNormalize(newup);
9760                         // make deformed versions of only the model vertices used by the specified surfaces
9761                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9762                         {
9763                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9764                                 // a single autosprite surface can contain multiple sprites...
9765                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9766                                 {
9767                                         VectorClear(center);
9768                                         for (i = 0;i < 4;i++)
9769                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9770                                         VectorScale(center, 0.25f, center);
9771                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
9772                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
9773                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
9774                                         for (i = 0;i < 4;i++)
9775                                         {
9776                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
9777                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9778                                         }
9779                                 }
9780                                 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);
9781                                 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);
9782                         }
9783                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9784                         rsurface.vertex3f_bufferobject = 0;
9785                         rsurface.vertex3f_bufferoffset = 0;
9786                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9787                         rsurface.svector3f_bufferobject = 0;
9788                         rsurface.svector3f_bufferoffset = 0;
9789                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9790                         rsurface.tvector3f_bufferobject = 0;
9791                         rsurface.tvector3f_bufferoffset = 0;
9792                         rsurface.normal3f = rsurface.array_deformednormal3f;
9793                         rsurface.normal3f_bufferobject = 0;
9794                         rsurface.normal3f_bufferoffset = 0;
9795                         break;
9796                 case Q3DEFORM_AUTOSPRITE2:
9797                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9798                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9799                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9800                         VectorNormalize(newforward);
9801                         VectorNormalize(newright);
9802                         VectorNormalize(newup);
9803                         // make deformed versions of only the model vertices used by the specified surfaces
9804                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9805                         {
9806                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9807                                 const float *v1, *v2;
9808                                 vec3_t start, end;
9809                                 float f, l;
9810                                 struct
9811                                 {
9812                                         float length2;
9813                                         const float *v1;
9814                                         const float *v2;
9815                                 }
9816                                 shortest[2];
9817                                 memset(shortest, 0, sizeof(shortest));
9818                                 // a single autosprite surface can contain multiple sprites...
9819                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9820                                 {
9821                                         VectorClear(center);
9822                                         for (i = 0;i < 4;i++)
9823                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9824                                         VectorScale(center, 0.25f, center);
9825                                         // find the two shortest edges, then use them to define the
9826                                         // axis vectors for rotating around the central axis
9827                                         for (i = 0;i < 6;i++)
9828                                         {
9829                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
9830                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
9831 #if 0
9832                                                 Debug_PolygonBegin(NULL, 0);
9833                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
9834                                                 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);
9835                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
9836                                                 Debug_PolygonEnd();
9837 #endif
9838                                                 l = VectorDistance2(v1, v2);
9839                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9840                                                 if (v1[2] != v2[2])
9841                                                         l += (1.0f / 1024.0f);
9842                                                 if (shortest[0].length2 > l || i == 0)
9843                                                 {
9844                                                         shortest[1] = shortest[0];
9845                                                         shortest[0].length2 = l;
9846                                                         shortest[0].v1 = v1;
9847                                                         shortest[0].v2 = v2;
9848                                                 }
9849                                                 else if (shortest[1].length2 > l || i == 1)
9850                                                 {
9851                                                         shortest[1].length2 = l;
9852                                                         shortest[1].v1 = v1;
9853                                                         shortest[1].v2 = v2;
9854                                                 }
9855                                         }
9856                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9857                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9858 #if 0
9859                                         Debug_PolygonBegin(NULL, 0);
9860                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
9861                                         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);
9862                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
9863                                         Debug_PolygonEnd();
9864 #endif
9865                                         // this calculates the right vector from the shortest edge
9866                                         // and the up vector from the edge midpoints
9867                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9868                                         VectorNormalize(right);
9869                                         VectorSubtract(end, start, up);
9870                                         VectorNormalize(up);
9871                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9872                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9873                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9874                                         VectorNegate(forward, forward);
9875                                         VectorReflect(forward, 0, up, forward);
9876                                         VectorNormalize(forward);
9877                                         CrossProduct(up, forward, newright);
9878                                         VectorNormalize(newright);
9879 #if 0
9880                                         Debug_PolygonBegin(NULL, 0);
9881                                         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);
9882                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
9883                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
9884                                         Debug_PolygonEnd();
9885 #endif
9886 #if 0
9887                                         Debug_PolygonBegin(NULL, 0);
9888                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
9889                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
9890                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
9891                                         Debug_PolygonEnd();
9892 #endif
9893                                         // rotate the quad around the up axis vector, this is made
9894                                         // especially easy by the fact we know the quad is flat,
9895                                         // so we only have to subtract the center position and
9896                                         // measure distance along the right vector, and then
9897                                         // multiply that by the newright vector and add back the
9898                                         // center position
9899                                         // we also need to subtract the old position to undo the
9900                                         // displacement from the center, which we do with a
9901                                         // DotProduct, the subtraction/addition of center is also
9902                                         // optimized into DotProducts here
9903                                         l = DotProduct(right, center);
9904                                         for (i = 0;i < 4;i++)
9905                                         {
9906                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
9907                                                 f = DotProduct(right, v1) - l;
9908                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9909                                         }
9910                                 }
9911                                 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);
9912                                 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);
9913                         }
9914                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9915                         rsurface.vertex3f_bufferobject = 0;
9916                         rsurface.vertex3f_bufferoffset = 0;
9917                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9918                         rsurface.svector3f_bufferobject = 0;
9919                         rsurface.svector3f_bufferoffset = 0;
9920                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9921                         rsurface.tvector3f_bufferobject = 0;
9922                         rsurface.tvector3f_bufferoffset = 0;
9923                         rsurface.normal3f = rsurface.array_deformednormal3f;
9924                         rsurface.normal3f_bufferobject = 0;
9925                         rsurface.normal3f_bufferoffset = 0;
9926                         break;
9927                 case Q3DEFORM_NORMAL:
9928                         // deform the normals to make reflections wavey
9929                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9930                         {
9931                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9932                                 for (j = 0;j < surface->num_vertices;j++)
9933                                 {
9934                                         float vertex[3];
9935                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
9936                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
9937                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
9938                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9939                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9940                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9941                                         VectorNormalize(normal);
9942                                 }
9943                                 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);
9944                         }
9945                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9946                         rsurface.svector3f_bufferobject = 0;
9947                         rsurface.svector3f_bufferoffset = 0;
9948                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9949                         rsurface.tvector3f_bufferobject = 0;
9950                         rsurface.tvector3f_bufferoffset = 0;
9951                         rsurface.normal3f = rsurface.array_deformednormal3f;
9952                         rsurface.normal3f_bufferobject = 0;
9953                         rsurface.normal3f_bufferoffset = 0;
9954                         break;
9955                 case Q3DEFORM_WAVE:
9956                         // deform vertex array to make wavey water and flags and such
9957                         waveparms[0] = deform->waveparms[0];
9958                         waveparms[1] = deform->waveparms[1];
9959                         waveparms[2] = deform->waveparms[2];
9960                         waveparms[3] = deform->waveparms[3];
9961                         // this is how a divisor of vertex influence on deformation
9962                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9963                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9964                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9965                         {
9966                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9967                                 for (j = 0;j < surface->num_vertices;j++)
9968                                 {
9969                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
9970                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9971                                         // if the wavefunc depends on time, evaluate it per-vertex
9972                                         if (waveparms[3])
9973                                         {
9974                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
9975                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9976                                         }
9977                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9978                                 }
9979                         }
9980                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9981                         rsurface.vertex3f_bufferobject = 0;
9982                         rsurface.vertex3f_bufferoffset = 0;
9983                         break;
9984                 case Q3DEFORM_BULGE:
9985                         // deform vertex array to make the surface have moving bulges
9986                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9987                         {
9988                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9989                                 for (j = 0;j < surface->num_vertices;j++)
9990                                 {
9991                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
9992                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9993                                 }
9994                         }
9995                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9996                         rsurface.vertex3f_bufferobject = 0;
9997                         rsurface.vertex3f_bufferoffset = 0;
9998                         break;
9999                 case Q3DEFORM_MOVE:
10000                         // deform vertex array
10001                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10002                         VectorScale(deform->parms, scale, waveparms);
10003                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10004                         {
10005                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10006                                 for (j = 0;j < surface->num_vertices;j++)
10007                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
10008                         }
10009                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
10010                         rsurface.vertex3f_bufferobject = 0;
10011                         rsurface.vertex3f_bufferoffset = 0;
10012                         break;
10013                 }
10014         }
10015         // generate texcoords based on the chosen texcoord source
10016         switch(rsurface.texture->tcgen.tcgen)
10017         {
10018         default:
10019         case Q3TCGEN_TEXTURE:
10020                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
10021                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
10022                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
10023                 break;
10024         case Q3TCGEN_LIGHTMAP:
10025                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
10026                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
10027                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
10028                 break;
10029         case Q3TCGEN_VECTOR:
10030                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10031                 {
10032                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10033                         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)
10034                         {
10035                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
10036                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
10037                         }
10038                 }
10039                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
10040                 rsurface.texcoordtexture2f_bufferobject  = 0;
10041                 rsurface.texcoordtexture2f_bufferoffset  = 0;
10042                 break;
10043         case Q3TCGEN_ENVIRONMENT:
10044                 // make environment reflections using a spheremap
10045                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10046                 {
10047                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10048                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
10049                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
10050                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
10051                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
10052                         {
10053                                 // identical to Q3A's method, but executed in worldspace so
10054                                 // carried models can be shiny too
10055
10056                                 float viewer[3], d, reflected[3], worldreflected[3];
10057
10058                                 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
10059                                 // VectorNormalize(viewer);
10060
10061                                 d = DotProduct(normal, viewer);
10062
10063                                 reflected[0] = normal[0]*2*d - viewer[0];
10064                                 reflected[1] = normal[1]*2*d - viewer[1];
10065                                 reflected[2] = normal[2]*2*d - viewer[2];
10066                                 // note: this is proportinal to viewer, so we can normalize later
10067
10068                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10069                                 VectorNormalize(worldreflected);
10070
10071                                 // note: this sphere map only uses world x and z!
10072                                 // so positive and negative y will LOOK THE SAME.
10073                                 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
10074                                 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
10075                         }
10076                 }
10077                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
10078                 rsurface.texcoordtexture2f_bufferobject  = 0;
10079                 rsurface.texcoordtexture2f_bufferoffset  = 0;
10080                 break;
10081         }
10082         // the only tcmod that needs software vertex processing is turbulent, so
10083         // check for it here and apply the changes if needed
10084         // and we only support that as the first one
10085         // (handling a mixture of turbulent and other tcmods would be problematic
10086         //  without punting it entirely to a software path)
10087         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10088         {
10089                 amplitude = rsurface.texture->tcmods[0].parms[1];
10090                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
10091                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10092                 {
10093                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10094                         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)
10095                         {
10096                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10097                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10098                         }
10099                 }
10100                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
10101                 rsurface.texcoordtexture2f_bufferobject  = 0;
10102                 rsurface.texcoordtexture2f_bufferoffset  = 0;
10103         }
10104         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
10105         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
10106         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
10107         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
10108 }
10109
10110 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10111 {
10112         int i, j;
10113         const msurface_t *surface = texturesurfacelist[0];
10114         const msurface_t *surface2;
10115         int firstvertex;
10116         int endvertex;
10117         int numvertices;
10118         int numtriangles;
10119         // TODO: lock all array ranges before render, rather than on each surface
10120         if (texturenumsurfaces == 1)
10121                 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);
10122         else if (r_batchmode.integer == 2)
10123         {
10124                 #define MAXBATCHTRIANGLES 4096
10125                 int batchtriangles = 0;
10126                 static int batchelements[MAXBATCHTRIANGLES*3];
10127                 for (i = 0;i < texturenumsurfaces;i = j)
10128                 {
10129                         surface = texturesurfacelist[i];
10130                         j = i + 1;
10131                         if (surface->num_triangles > MAXBATCHTRIANGLES)
10132                         {
10133                                 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);
10134                                 continue;
10135                         }
10136                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
10137                         batchtriangles = surface->num_triangles;
10138                         firstvertex = surface->num_firstvertex;
10139                         endvertex = surface->num_firstvertex + surface->num_vertices;
10140                         for (;j < texturenumsurfaces;j++)
10141                         {
10142                                 surface2 = texturesurfacelist[j];
10143                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
10144                                         break;
10145                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
10146                                 batchtriangles += surface2->num_triangles;
10147                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
10148                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
10149                         }
10150                         surface2 = texturesurfacelist[j-1];
10151                         numvertices = endvertex - firstvertex;
10152                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
10153                 }
10154         }
10155         else if (r_batchmode.integer == 1)
10156         {
10157                 for (i = 0;i < texturenumsurfaces;i = j)
10158                 {
10159                         surface = texturesurfacelist[i];
10160                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10161                                 if (texturesurfacelist[j] != surface2)
10162                                         break;
10163                         surface2 = texturesurfacelist[j-1];
10164                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
10165                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
10166                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10167                 }
10168         }
10169         else
10170         {
10171                 for (i = 0;i < texturenumsurfaces;i++)
10172                 {
10173                         surface = texturesurfacelist[i];
10174                         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);
10175                 }
10176         }
10177 }
10178
10179 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
10180 {
10181         switch(vid.renderpath)
10182         {
10183         case RENDERPATH_CGGL:
10184 #ifdef SUPPORTCG
10185                 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
10186                 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
10187 #endif
10188                 break;
10189         case RENDERPATH_GL20:
10190                 if (r_glsl_permutation->loc_Texture_Lightmap  >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
10191                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
10192                 break;
10193         case RENDERPATH_GL13:
10194         case RENDERPATH_GL11:
10195                 R_Mesh_TexBind(0, surface->lightmaptexture);
10196                 break;
10197         }
10198 }
10199
10200 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
10201 {
10202         // pick the closest matching water plane and bind textures
10203         int planeindex, vertexindex;
10204         float d, bestd;
10205         vec3_t vert;
10206         const float *v;
10207         r_waterstate_waterplane_t *p, *bestp;
10208         bestd = 0;
10209         bestp = NULL;
10210         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
10211         {
10212                 d = 0;
10213                 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
10214                 {
10215                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10216                         d += fabs(PlaneDiff(vert, &p->plane));
10217                 }
10218                 if (bestd > d || !bestp)
10219                 {
10220                         bestd = d;
10221                         bestp = p;
10222                 }
10223         }
10224         switch(vid.renderpath)
10225         {
10226         case RENDERPATH_CGGL:
10227 #ifdef SUPPORTCG
10228                 if (r_cg_permutation->fp_Texture_Refraction) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR
10229                 if (r_cg_permutation->fp_Texture_Reflection) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR
10230 #endif
10231                 break;
10232         case RENDERPATH_GL20:
10233                 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
10234                 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
10235                 break;
10236         case RENDERPATH_GL13:
10237         case RENDERPATH_GL11:
10238                 break;
10239         }
10240 }
10241
10242 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10243 {
10244         int i;
10245         const msurface_t *surface;
10246         if (r_waterstate.renderingscene)
10247                 return;
10248         for (i = 0;i < texturenumsurfaces;i++)
10249         {
10250                 surface = texturesurfacelist[i];
10251                 RSurf_BindLightmapForSurface(surface);
10252                 RSurf_BindReflectionForSurface(surface);
10253                 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);
10254         }
10255 }
10256
10257 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10258 {
10259         int i;
10260         int j;
10261         const msurface_t *surface = texturesurfacelist[0];
10262         const msurface_t *surface2;
10263         int firstvertex;
10264         int endvertex;
10265         int numvertices;
10266         int numtriangles;
10267         if (texturenumsurfaces == 1)
10268         {
10269                 RSurf_BindLightmapForSurface(surface);
10270                 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);
10271         }
10272         else if (r_batchmode.integer == 2)
10273         {
10274 #define MAXBATCHTRIANGLES 4096
10275                 int batchtriangles = 0;
10276                 static int batchelements[MAXBATCHTRIANGLES*3];
10277                 for (i = 0;i < texturenumsurfaces;i = j)
10278                 {
10279                         surface = texturesurfacelist[i];
10280                         RSurf_BindLightmapForSurface(surface);
10281                         j = i + 1;
10282                         if (surface->num_triangles > MAXBATCHTRIANGLES)
10283                         {
10284                                 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);
10285                                 continue;
10286                         }
10287                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
10288                         batchtriangles = surface->num_triangles;
10289                         firstvertex = surface->num_firstvertex;
10290                         endvertex = surface->num_firstvertex + surface->num_vertices;
10291                         for (;j < texturenumsurfaces;j++)
10292                         {
10293                                 surface2 = texturesurfacelist[j];
10294                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
10295                                         break;
10296                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
10297                                 batchtriangles += surface2->num_triangles;
10298                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
10299                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
10300                         }
10301                         surface2 = texturesurfacelist[j-1];
10302                         numvertices = endvertex - firstvertex;
10303                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
10304                 }
10305         }
10306         else if (r_batchmode.integer == 1)
10307         {
10308 #if 0
10309                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
10310                 for (i = 0;i < texturenumsurfaces;i = j)
10311                 {
10312                         surface = texturesurfacelist[i];
10313                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10314                                 if (texturesurfacelist[j] != surface2)
10315                                         break;
10316                         Con_Printf(" %i", j - i);
10317                 }
10318                 Con_Printf("\n");
10319                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
10320 #endif
10321                 for (i = 0;i < texturenumsurfaces;i = j)
10322                 {
10323                         surface = texturesurfacelist[i];
10324                         RSurf_BindLightmapForSurface(surface);
10325                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10326                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
10327                                         break;
10328 #if 0
10329                         Con_Printf(" %i", j - i);
10330 #endif
10331                         surface2 = texturesurfacelist[j-1];
10332                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
10333                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
10334                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10335                 }
10336 #if 0
10337                 Con_Printf("\n");
10338 #endif
10339         }
10340         else
10341         {
10342                 for (i = 0;i < texturenumsurfaces;i++)
10343                 {
10344                         surface = texturesurfacelist[i];
10345                         RSurf_BindLightmapForSurface(surface);
10346                         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);
10347                 }
10348         }
10349 }
10350
10351 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10352 {
10353         int j;
10354         int texturesurfaceindex;
10355         if (r_showsurfaces.integer == 2)
10356         {
10357                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10358                 {
10359                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10360                         for (j = 0;j < surface->num_triangles;j++)
10361                         {
10362                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
10363                                 GL_Color(f, f, f, 1);
10364                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10365                         }
10366                 }
10367         }
10368         else
10369         {
10370                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10371                 {
10372                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10373                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
10374                         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);
10375                         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);
10376                 }
10377         }
10378 }
10379
10380 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10381 {
10382         int texturesurfaceindex;
10383         int i;
10384         const float *v;
10385         float *c2;
10386         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10387         {
10388                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10389                 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)
10390                 {
10391                         c2[0] = 0.5;
10392                         c2[1] = 0.5;
10393                         c2[2] = 0.5;
10394                         c2[3] = 1;
10395                 }
10396         }
10397         rsurface.lightmapcolor4f = rsurface.array_color4f;
10398         rsurface.lightmapcolor4f_bufferobject = 0;
10399         rsurface.lightmapcolor4f_bufferoffset = 0;
10400 }
10401
10402 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10403 {
10404         int texturesurfaceindex;
10405         int i;
10406         float f;
10407         const float *v;
10408         const float *c;
10409         float *c2;
10410         if (rsurface.lightmapcolor4f)
10411         {
10412                 // generate color arrays for the surfaces in this list
10413                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10414                 {
10415                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10416                         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)
10417                         {
10418                                 f = RSurf_FogVertex(v);
10419                                 c2[0] = c[0] * f;
10420                                 c2[1] = c[1] * f;
10421                                 c2[2] = c[2] * f;
10422                                 c2[3] = c[3];
10423                         }
10424                 }
10425         }
10426         else
10427         {
10428                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10429                 {
10430                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10431                         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)
10432                         {
10433                                 f = RSurf_FogVertex(v);
10434                                 c2[0] = f;
10435                                 c2[1] = f;
10436                                 c2[2] = f;
10437                                 c2[3] = 1;
10438                         }
10439                 }
10440         }
10441         rsurface.lightmapcolor4f = rsurface.array_color4f;
10442         rsurface.lightmapcolor4f_bufferobject = 0;
10443         rsurface.lightmapcolor4f_bufferoffset = 0;
10444 }
10445
10446 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10447 {
10448         int texturesurfaceindex;
10449         int i;
10450         float f;
10451         const float *v;
10452         const float *c;
10453         float *c2;
10454         if (!rsurface.lightmapcolor4f)
10455                 return;
10456         // generate color arrays for the surfaces in this list
10457         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10458         {
10459                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10460                 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)
10461                 {
10462                         f = RSurf_FogVertex(v);
10463                         c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10464                         c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10465                         c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10466                         c2[3] = c[3];
10467                 }
10468         }
10469         rsurface.lightmapcolor4f = rsurface.array_color4f;
10470         rsurface.lightmapcolor4f_bufferobject = 0;
10471         rsurface.lightmapcolor4f_bufferoffset = 0;
10472 }
10473
10474 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
10475 {
10476         int texturesurfaceindex;
10477         int i;
10478         const float *c;
10479         float *c2;
10480         if (!rsurface.lightmapcolor4f)
10481                 return;
10482         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10483         {
10484                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10485                 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)
10486                 {
10487                         c2[0] = c[0] * r;
10488                         c2[1] = c[1] * g;
10489                         c2[2] = c[2] * b;
10490                         c2[3] = c[3] * a;
10491                 }
10492         }
10493         rsurface.lightmapcolor4f = rsurface.array_color4f;
10494         rsurface.lightmapcolor4f_bufferobject = 0;
10495         rsurface.lightmapcolor4f_bufferoffset = 0;
10496 }
10497
10498 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10499 {
10500         int texturesurfaceindex;
10501         int i;
10502         const float *c;
10503         float *c2;
10504         if (!rsurface.lightmapcolor4f)
10505                 return;
10506         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10507         {
10508                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10509                 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)
10510                 {
10511                         c2[0] = c[0] + r_refdef.scene.ambient;
10512                         c2[1] = c[1] + r_refdef.scene.ambient;
10513                         c2[2] = c[2] + r_refdef.scene.ambient;
10514                         c2[3] = c[3];
10515                 }
10516         }
10517         rsurface.lightmapcolor4f = rsurface.array_color4f;
10518         rsurface.lightmapcolor4f_bufferobject = 0;
10519         rsurface.lightmapcolor4f_bufferoffset = 0;
10520 }
10521
10522 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10523 {
10524         // TODO: optimize
10525         rsurface.lightmapcolor4f = NULL;
10526         rsurface.lightmapcolor4f_bufferobject = 0;
10527         rsurface.lightmapcolor4f_bufferoffset = 0;
10528         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10529         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10530         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10531         GL_Color(r, g, b, a);
10532         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10533 }
10534
10535 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10536 {
10537         // TODO: optimize applyfog && applycolor case
10538         // just apply fog if necessary, and tint the fog color array if necessary
10539         rsurface.lightmapcolor4f = NULL;
10540         rsurface.lightmapcolor4f_bufferobject = 0;
10541         rsurface.lightmapcolor4f_bufferoffset = 0;
10542         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10543         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10544         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10545         GL_Color(r, g, b, a);
10546         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10547 }
10548
10549 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10550 {
10551         int texturesurfaceindex;
10552         int i;
10553         float *c;
10554         // TODO: optimize
10555         if (texturesurfacelist[0]->lightmapinfo)
10556         {
10557                 // generate color arrays for the surfaces in this list
10558                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10559                 {
10560                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10561                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
10562                         {
10563                                 if (surface->lightmapinfo->samples)
10564                                 {
10565                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
10566                                         float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
10567                                         VectorScale(lm, scale, c);
10568                                         if (surface->lightmapinfo->styles[1] != 255)
10569                                         {
10570                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
10571                                                 lm += size3;
10572                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
10573                                                 VectorMA(c, scale, lm, c);
10574                                                 if (surface->lightmapinfo->styles[2] != 255)
10575                                                 {
10576                                                         lm += size3;
10577                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
10578                                                         VectorMA(c, scale, lm, c);
10579                                                         if (surface->lightmapinfo->styles[3] != 255)
10580                                                         {
10581                                                                 lm += size3;
10582                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
10583                                                                 VectorMA(c, scale, lm, c);
10584                                                         }
10585                                                 }
10586                                         }
10587                                 }
10588                                 else
10589                                         VectorClear(c);
10590                                 c[3] = 1;
10591                         }
10592                 }
10593                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10594                 rsurface.lightmapcolor4f_bufferobject = 0;
10595                 rsurface.lightmapcolor4f_bufferoffset = 0;
10596         }
10597         else
10598         {
10599                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10600                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10601                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10602         }
10603         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10604         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10605         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10606         GL_Color(r, g, b, a);
10607         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10608 }
10609
10610 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
10611 {
10612         int texturesurfaceindex;
10613         int i;
10614         float f;
10615         float alpha;
10616         const float *v;
10617         const float *n;
10618         float *c;
10619         vec3_t ambientcolor;
10620         vec3_t diffusecolor;
10621         vec3_t lightdir;
10622         // TODO: optimize
10623         // model lighting
10624         VectorCopy(rsurface.modellight_lightdir, lightdir);
10625         f = 0.5f * r_refdef.lightmapintensity;
10626         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10627         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10628         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10629         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10630         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10631         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10632         alpha = *a;
10633         if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
10634         {
10635                 // generate color arrays for the surfaces in this list
10636                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10637                 {
10638                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10639                         int numverts = surface->num_vertices;
10640                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
10641                         n = rsurface.normal3f + 3 * surface->num_firstvertex;
10642                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
10643                         // q3-style directional shading
10644                         for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
10645                         {
10646                                 if ((f = DotProduct(n, lightdir)) > 0)
10647                                         VectorMA(ambientcolor, f, diffusecolor, c);
10648                                 else
10649                                         VectorCopy(ambientcolor, c);
10650                                 c[3] = alpha;
10651                         }
10652                 }
10653                 *r = 1;
10654                 *g = 1;
10655                 *b = 1;
10656                 *a = 1;
10657                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10658                 rsurface.lightmapcolor4f_bufferobject = 0;
10659                 rsurface.lightmapcolor4f_bufferoffset = 0;
10660                 *applycolor = false;
10661         }
10662         else
10663         {
10664                 *r = ambientcolor[0];
10665                 *g = ambientcolor[1];
10666                 *b = ambientcolor[2];
10667                 rsurface.lightmapcolor4f = NULL;
10668                 rsurface.lightmapcolor4f_bufferobject = 0;
10669                 rsurface.lightmapcolor4f_bufferoffset = 0;
10670         }
10671 }
10672
10673 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10674 {
10675         RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
10676         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10677         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10678         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10679         GL_Color(r, g, b, a);
10680         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10681 }
10682
10683 void RSurf_SetupDepthAndCulling(void)
10684 {
10685         // submodels are biased to avoid z-fighting with world surfaces that they
10686         // may be exactly overlapping (avoids z-fighting artifacts on certain
10687         // doors and things in Quake maps)
10688         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10689         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10690         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10691         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10692 }
10693
10694 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10695 {
10696         // transparent sky would be ridiculous
10697         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10698                 return;
10699         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10700         skyrenderlater = true;
10701         RSurf_SetupDepthAndCulling();
10702         GL_DepthMask(true);
10703         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10704         // skymasking on them, and Quake3 never did sky masking (unlike
10705         // software Quake and software Quake2), so disable the sky masking
10706         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10707         // and skymasking also looks very bad when noclipping outside the
10708         // level, so don't use it then either.
10709         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
10710         {
10711                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10712                 R_Mesh_ColorPointer(NULL, 0, 0);
10713                 R_Mesh_ResetTextureState();
10714                 if (skyrendermasked)
10715                 {
10716                         R_SetupShader_DepthOrShadow();
10717                         // depth-only (masking)
10718                         GL_ColorMask(0,0,0,0);
10719                         // just to make sure that braindead drivers don't draw
10720                         // anything despite that colormask...
10721                         GL_BlendFunc(GL_ZERO, GL_ONE);
10722                 }
10723                 else
10724                 {
10725                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10726                         // fog sky
10727                         GL_BlendFunc(GL_ONE, GL_ZERO);
10728                 }
10729                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10730                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10731                 if (skyrendermasked)
10732                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10733         }
10734         R_Mesh_ResetTextureState();
10735         GL_Color(1, 1, 1, 1);
10736 }
10737
10738 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10739 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10740 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10741 {
10742         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
10743                 return;
10744         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10745         if (prepass)
10746         {
10747                 // render screenspace normalmap to texture
10748                 GL_DepthMask(true);
10749                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY);
10750                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10751         }
10752         else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !r_waterstate.renderingscene)
10753         {
10754                 // render water or distortion background, then blend surface on top
10755                 GL_DepthMask(true);
10756                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
10757                 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10758                 GL_DepthMask(false);
10759                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
10760                 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10761                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10762                 else
10763                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10764         }
10765         else
10766         {
10767                 // render surface normally
10768                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10769                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
10770                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
10771                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10772                 else if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10773                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10774                 else
10775                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10776         }
10777 }
10778
10779 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10780 {
10781         // OpenGL 1.3 path - anything not completely ancient
10782         int texturesurfaceindex;
10783         qboolean applycolor;
10784         qboolean applyfog;
10785         int layerindex;
10786         const texturelayer_t *layer;
10787         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10788
10789         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10790         {
10791                 vec4_t layercolor;
10792                 int layertexrgbscale;
10793                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10794                 {
10795                         if (layerindex == 0)
10796                                 GL_AlphaTest(true);
10797                         else
10798                         {
10799                                 GL_AlphaTest(false);
10800                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10801                         }
10802                 }
10803                 GL_DepthMask(layer->depthmask && writedepth);
10804                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10805                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10806                 {
10807                         layertexrgbscale = 4;
10808                         VectorScale(layer->color, 0.25f, layercolor);
10809                 }
10810                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10811                 {
10812                         layertexrgbscale = 2;
10813                         VectorScale(layer->color, 0.5f, layercolor);
10814                 }
10815                 else
10816                 {
10817                         layertexrgbscale = 1;
10818                         VectorScale(layer->color, 1.0f, layercolor);
10819                 }
10820                 layercolor[3] = layer->color[3];
10821                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10822                 R_Mesh_ColorPointer(NULL, 0, 0);
10823                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10824                 switch (layer->type)
10825                 {
10826                 case TEXTURELAYERTYPE_LITTEXTURE:
10827                         // single-pass lightmapped texture with 2x rgbscale
10828                         R_Mesh_TexBind(0, r_texture_white);
10829                         R_Mesh_TexMatrix(0, NULL);
10830                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10831                         R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10832                         R_Mesh_TexBind(1, layer->texture);
10833                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10834                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10835                         R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10836                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10837                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10838                         else if (rsurface.uselightmaptexture)
10839                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10840                         else
10841                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10842                         break;
10843                 case TEXTURELAYERTYPE_TEXTURE:
10844                         // singletexture unlit texture with transparency support
10845                         R_Mesh_TexBind(0, layer->texture);
10846                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10847                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10848                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10849                         R_Mesh_TexBind(1, 0);
10850                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10851                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10852                         break;
10853                 case TEXTURELAYERTYPE_FOG:
10854                         // singletexture fogging
10855                         if (layer->texture)
10856                         {
10857                                 R_Mesh_TexBind(0, layer->texture);
10858                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10859                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10860                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10861                         }
10862                         else
10863                         {
10864                                 R_Mesh_TexBind(0, 0);
10865                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10866                         }
10867                         R_Mesh_TexBind(1, 0);
10868                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10869                         // generate a color array for the fog pass
10870                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10871                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10872                         {
10873                                 int i;
10874                                 float f;
10875                                 const float *v;
10876                                 float *c;
10877                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10878                                 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)
10879                                 {
10880                                         f = 1 - RSurf_FogVertex(v);
10881                                         c[0] = layercolor[0];
10882                                         c[1] = layercolor[1];
10883                                         c[2] = layercolor[2];
10884                                         c[3] = f * layercolor[3];
10885                                 }
10886                         }
10887                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10888                         break;
10889                 default:
10890                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10891                 }
10892         }
10893         CHECKGLERROR
10894         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10895         {
10896                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10897                 GL_AlphaTest(false);
10898         }
10899 }
10900
10901 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10902 {
10903         // OpenGL 1.1 - crusty old voodoo path
10904         int texturesurfaceindex;
10905         qboolean applyfog;
10906         int layerindex;
10907         const texturelayer_t *layer;
10908         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10909
10910         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10911         {
10912                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10913                 {
10914                         if (layerindex == 0)
10915                                 GL_AlphaTest(true);
10916                         else
10917                         {
10918                                 GL_AlphaTest(false);
10919                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10920                         }
10921                 }
10922                 GL_DepthMask(layer->depthmask && writedepth);
10923                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10924                 R_Mesh_ColorPointer(NULL, 0, 0);
10925                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10926                 switch (layer->type)
10927                 {
10928                 case TEXTURELAYERTYPE_LITTEXTURE:
10929                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10930                         {
10931                                 // two-pass lit texture with 2x rgbscale
10932                                 // first the lightmap pass
10933                                 R_Mesh_TexBind(0, r_texture_white);
10934                                 R_Mesh_TexMatrix(0, NULL);
10935                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10936                                 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10937                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10938                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10939                                 else if (rsurface.uselightmaptexture)
10940                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10941                                 else
10942                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10943                                 // then apply the texture to it
10944                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10945                                 R_Mesh_TexBind(0, layer->texture);
10946                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10947                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10948                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10949                                 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);
10950                         }
10951                         else
10952                         {
10953                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10954                                 R_Mesh_TexBind(0, layer->texture);
10955                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10956                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10957                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10958                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10959                                         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);
10960                                 else
10961                                         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);
10962                         }
10963                         break;
10964                 case TEXTURELAYERTYPE_TEXTURE:
10965                         // singletexture unlit texture with transparency support
10966                         R_Mesh_TexBind(0, layer->texture);
10967                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10968                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10969                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10970                         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);
10971                         break;
10972                 case TEXTURELAYERTYPE_FOG:
10973                         // singletexture fogging
10974                         if (layer->texture)
10975                         {
10976                                 R_Mesh_TexBind(0, layer->texture);
10977                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10978                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10979                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10980                         }
10981                         else
10982                         {
10983                                 R_Mesh_TexBind(0, 0);
10984                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10985                         }
10986                         // generate a color array for the fog pass
10987                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10988                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10989                         {
10990                                 int i;
10991                                 float f;
10992                                 const float *v;
10993                                 float *c;
10994                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10995                                 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)
10996                                 {
10997                                         f = 1 - RSurf_FogVertex(v);
10998                                         c[0] = layer->color[0];
10999                                         c[1] = layer->color[1];
11000                                         c[2] = layer->color[2];
11001                                         c[3] = f * layer->color[3];
11002                                 }
11003                         }
11004                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11005                         break;
11006                 default:
11007                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11008                 }
11009         }
11010         CHECKGLERROR
11011         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11012         {
11013                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
11014                 GL_AlphaTest(false);
11015         }
11016 }
11017
11018 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11019 {
11020         float c[4];
11021
11022         GL_AlphaTest(false);
11023         R_Mesh_ColorPointer(NULL, 0, 0);
11024         R_Mesh_ResetTextureState();
11025         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11026
11027         if(rsurface.texture && rsurface.texture->currentskinframe)
11028         {
11029                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11030                 c[3] *= rsurface.texture->currentalpha;
11031         }
11032         else
11033         {
11034                 c[0] = 1;
11035                 c[1] = 0;
11036                 c[2] = 1;
11037                 c[3] = 1;
11038         }
11039
11040         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11041         {
11042                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11043                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11044                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11045         }
11046
11047         // brighten it up (as texture value 127 means "unlit")
11048         c[0] *= 2 * r_refdef.view.colorscale;
11049         c[1] *= 2 * r_refdef.view.colorscale;
11050         c[2] *= 2 * r_refdef.view.colorscale;
11051
11052         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11053                 c[3] *= r_wateralpha.value;
11054
11055         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11056         {
11057                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11058                 GL_DepthMask(false);
11059         }
11060         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11061         {
11062                 GL_BlendFunc(GL_ONE, GL_ONE);
11063                 GL_DepthMask(false);
11064         }
11065         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11066         {
11067                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11068                 GL_DepthMask(false);
11069         }
11070         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11071         {
11072                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11073                 GL_DepthMask(false);
11074         }
11075         else
11076         {
11077                 GL_BlendFunc(GL_ONE, GL_ZERO);
11078                 GL_DepthMask(writedepth);
11079         }
11080
11081         rsurface.lightmapcolor4f = NULL;
11082
11083         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11084         {
11085                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11086
11087                 rsurface.lightmapcolor4f = NULL;
11088                 rsurface.lightmapcolor4f_bufferobject = 0;
11089                 rsurface.lightmapcolor4f_bufferoffset = 0;
11090         }
11091         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11092         {
11093                 qboolean applycolor = true;
11094                 float one = 1.0;
11095
11096                 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
11097
11098                 r_refdef.lightmapintensity = 1;
11099                 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
11100                 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11101         }
11102         else
11103         {
11104                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11105
11106                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
11107                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
11108                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11109         }
11110
11111         if(!rsurface.lightmapcolor4f)
11112                 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
11113
11114         RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
11115         RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
11116         if(r_refdef.fogenabled)
11117                 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
11118
11119         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
11120         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11121 }
11122
11123 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11124 {
11125         CHECKGLERROR
11126         RSurf_SetupDepthAndCulling();
11127         if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
11128         {
11129                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
11130                 return;
11131         }
11132         switch (vid.renderpath)
11133         {
11134         case RENDERPATH_GL20:
11135         case RENDERPATH_CGGL:
11136                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11137                 break;
11138         case RENDERPATH_GL13:
11139                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11140                 break;
11141         case RENDERPATH_GL11:
11142                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11143                 break;
11144         }
11145         CHECKGLERROR
11146 }
11147
11148 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11149 {
11150         CHECKGLERROR
11151         RSurf_SetupDepthAndCulling();
11152         if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
11153         {
11154                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
11155                 return;
11156         }
11157         switch (vid.renderpath)
11158         {
11159         case RENDERPATH_GL20:
11160         case RENDERPATH_CGGL:
11161                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11162                 break;
11163         case RENDERPATH_GL13:
11164                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11165                 break;
11166         case RENDERPATH_GL11:
11167                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11168                 break;
11169         }
11170         CHECKGLERROR
11171 }
11172
11173 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11174 {
11175         int i, j;
11176         int texturenumsurfaces, endsurface;
11177         texture_t *texture;
11178         const msurface_t *surface;
11179         const msurface_t *texturesurfacelist[256];
11180
11181         // if the model is static it doesn't matter what value we give for
11182         // wantnormals and wanttangents, so this logic uses only rules applicable
11183         // to a model, knowing that they are meaningless otherwise
11184         if (ent == r_refdef.scene.worldentity)
11185                 RSurf_ActiveWorldEntity();
11186         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11187                 RSurf_ActiveModelEntity(ent, false, false, false);
11188         else
11189         {
11190                 switch (vid.renderpath)
11191                 {
11192                 case RENDERPATH_GL20:
11193                 case RENDERPATH_CGGL:
11194                         RSurf_ActiveModelEntity(ent, true, true, false);
11195                         break;
11196                 case RENDERPATH_GL13:
11197                 case RENDERPATH_GL11:
11198                         RSurf_ActiveModelEntity(ent, true, false, false);
11199                         break;
11200                 }
11201         }
11202
11203         if (r_transparentdepthmasking.integer)
11204         {
11205                 qboolean setup = false;
11206                 for (i = 0;i < numsurfaces;i = j)
11207                 {
11208                         j = i + 1;
11209                         surface = rsurface.modelsurfaces + surfacelist[i];
11210                         texture = surface->texture;
11211                         rsurface.texture = R_GetCurrentTexture(texture);
11212                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11213                         // scan ahead until we find a different texture
11214                         endsurface = min(i + 1024, numsurfaces);
11215                         texturenumsurfaces = 0;
11216                         texturesurfacelist[texturenumsurfaces++] = surface;
11217                         for (;j < endsurface;j++)
11218                         {
11219                                 surface = rsurface.modelsurfaces + surfacelist[j];
11220                                 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
11221                                         break;
11222                                 texturesurfacelist[texturenumsurfaces++] = surface;
11223                         }
11224                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11225                                 continue;
11226                         // render the range of surfaces as depth
11227                         if (!setup)
11228                         {
11229                                 setup = true;
11230                                 GL_ColorMask(0,0,0,0);
11231                                 GL_Color(1,1,1,1);
11232                                 GL_DepthTest(true);
11233                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11234                                 GL_DepthMask(true);
11235                                 GL_AlphaTest(false);
11236                                 R_Mesh_ColorPointer(NULL, 0, 0);
11237                                 R_Mesh_ResetTextureState();
11238                                 R_SetupShader_DepthOrShadow();
11239                         }
11240                         RSurf_SetupDepthAndCulling();
11241                         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11242                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11243                 }
11244                 if (setup)
11245                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11246         }
11247
11248         for (i = 0;i < numsurfaces;i = j)
11249         {
11250                 j = i + 1;
11251                 surface = rsurface.modelsurfaces + surfacelist[i];
11252                 texture = surface->texture;
11253                 rsurface.texture = R_GetCurrentTexture(texture);
11254                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11255                 // scan ahead until we find a different texture
11256                 endsurface = min(i + 1024, numsurfaces);
11257                 texturenumsurfaces = 0;
11258                 texturesurfacelist[texturenumsurfaces++] = surface;
11259                 for (;j < endsurface;j++)
11260                 {
11261                         surface = rsurface.modelsurfaces + surfacelist[j];
11262                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
11263                                 break;
11264                         texturesurfacelist[texturenumsurfaces++] = surface;
11265                 }
11266                 // render the range of surfaces
11267                 if (ent == r_refdef.scene.worldentity)
11268                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11269                 else
11270                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11271         }
11272         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11273         GL_AlphaTest(false);
11274 }
11275
11276 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
11277 {
11278         // transparent surfaces get pushed off into the transparent queue
11279         int surfacelistindex;
11280         const msurface_t *surface;
11281         vec3_t tempcenter, center;
11282         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11283         {
11284                 surface = texturesurfacelist[surfacelistindex];
11285                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11286                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11287                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11288                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11289                 if (queueentity->transparent_offset) // transparent offset
11290                 {
11291                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
11292                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
11293                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
11294                 }
11295                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
11296         }
11297 }
11298
11299 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11300 {
11301         const entity_render_t *queueentity = r_refdef.scene.worldentity;
11302         CHECKGLERROR
11303         if (depthonly)
11304         {
11305                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11306                         return;
11307                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11308                         return;
11309                 RSurf_SetupDepthAndCulling();
11310                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11311                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11312         }
11313         else if (prepass)
11314         {
11315                 if (!rsurface.texture->currentnumlayers)
11316                         return;
11317                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11318                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11319                 else
11320                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11321         }
11322         else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
11323         {
11324                 RSurf_SetupDepthAndCulling();
11325                 GL_AlphaTest(false);
11326                 R_Mesh_ColorPointer(NULL, 0, 0);
11327                 R_Mesh_ResetTextureState();
11328                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11329                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11330                 GL_DepthMask(true);
11331                 GL_BlendFunc(GL_ONE, GL_ZERO);
11332                 GL_Color(0, 0, 0, 1);
11333                 GL_DepthTest(writedepth);
11334                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11335         }
11336         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
11337         {
11338                 RSurf_SetupDepthAndCulling();
11339                 GL_AlphaTest(false);
11340                 R_Mesh_ColorPointer(NULL, 0, 0);
11341                 R_Mesh_ResetTextureState();
11342                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11343                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11344                 GL_DepthMask(true);
11345                 GL_BlendFunc(GL_ONE, GL_ZERO);
11346                 GL_DepthTest(true);
11347                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11348         }
11349         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11350                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11351         else if (!rsurface.texture->currentnumlayers)
11352                 return;
11353         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11354         {
11355                 // in the deferred case, transparent surfaces were queued during prepass
11356                 if (!r_shadow_usingdeferredprepass)
11357                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11358         }
11359         else
11360         {
11361                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11362                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11363         }
11364         CHECKGLERROR
11365 }
11366
11367 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11368 {
11369         int i, j;
11370         texture_t *texture;
11371         // break the surface list down into batches by texture and use of lightmapping
11372         for (i = 0;i < numsurfaces;i = j)
11373         {
11374                 j = i + 1;
11375                 // texture is the base texture pointer, rsurface.texture is the
11376                 // current frame/skin the texture is directing us to use (for example
11377                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11378                 // use skin 1 instead)
11379                 texture = surfacelist[i]->texture;
11380                 rsurface.texture = R_GetCurrentTexture(texture);
11381                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11382                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11383                 {
11384                         // if this texture is not the kind we want, skip ahead to the next one
11385                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11386                                 ;
11387                         continue;
11388                 }
11389                 // simply scan ahead until we find a different texture or lightmap state
11390                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11391                         ;
11392                 // render the range of surfaces
11393                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11394         }
11395 }
11396
11397 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
11398 {
11399         CHECKGLERROR
11400         if (depthonly)
11401         {
11402                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11403                         return;
11404                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11405                         return;
11406                 RSurf_SetupDepthAndCulling();
11407                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11408                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11409         }
11410         else if (prepass)
11411         {
11412                 if (!rsurface.texture->currentnumlayers)
11413                         return;
11414                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11415                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11416                 else
11417                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11418         }
11419         else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
11420         {
11421                 RSurf_SetupDepthAndCulling();
11422                 GL_AlphaTest(false);
11423                 R_Mesh_ColorPointer(NULL, 0, 0);
11424                 R_Mesh_ResetTextureState();
11425                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11426                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11427                 GL_DepthMask(true);
11428                 GL_BlendFunc(GL_ONE, GL_ZERO);
11429                 GL_Color(0, 0, 0, 1);
11430                 GL_DepthTest(writedepth);
11431                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11432         }
11433         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11434         {
11435                 RSurf_SetupDepthAndCulling();
11436                 GL_AlphaTest(false);
11437                 R_Mesh_ColorPointer(NULL, 0, 0);
11438                 R_Mesh_ResetTextureState();
11439                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11440                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11441                 GL_DepthMask(true);
11442                 GL_BlendFunc(GL_ONE, GL_ZERO);
11443                 GL_DepthTest(true);
11444                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11445         }
11446         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11447                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11448         else if (!rsurface.texture->currentnumlayers)
11449                 return;
11450         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11451         {
11452                 // in the deferred case, transparent surfaces were queued during prepass
11453                 if (!r_shadow_usingdeferredprepass)
11454                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11455         }
11456         else
11457         {
11458                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11459                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11460         }
11461         CHECKGLERROR
11462 }
11463
11464 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11465 {
11466         int i, j;
11467         texture_t *texture;
11468         // break the surface list down into batches by texture and use of lightmapping
11469         for (i = 0;i < numsurfaces;i = j)
11470         {
11471                 j = i + 1;
11472                 // texture is the base texture pointer, rsurface.texture is the
11473                 // current frame/skin the texture is directing us to use (for example
11474                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11475                 // use skin 1 instead)
11476                 texture = surfacelist[i]->texture;
11477                 rsurface.texture = R_GetCurrentTexture(texture);
11478                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11479                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11480                 {
11481                         // if this texture is not the kind we want, skip ahead to the next one
11482                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11483                                 ;
11484                         continue;
11485                 }
11486                 // simply scan ahead until we find a different texture or lightmap state
11487                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11488                         ;
11489                 // render the range of surfaces
11490                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
11491         }
11492 }
11493
11494 float locboxvertex3f[6*4*3] =
11495 {
11496         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11497         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11498         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11499         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11500         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11501         1,0,0, 0,0,0, 0,1,0, 1,1,0
11502 };
11503
11504 unsigned short locboxelements[6*2*3] =
11505 {
11506          0, 1, 2, 0, 2, 3,
11507          4, 5, 6, 4, 6, 7,
11508          8, 9,10, 8,10,11,
11509         12,13,14, 12,14,15,
11510         16,17,18, 16,18,19,
11511         20,21,22, 20,22,23
11512 };
11513
11514 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11515 {
11516         int i, j;
11517         cl_locnode_t *loc = (cl_locnode_t *)ent;
11518         vec3_t mins, size;
11519         float vertex3f[6*4*3];
11520         CHECKGLERROR
11521         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11522         GL_DepthMask(false);
11523         GL_DepthRange(0, 1);
11524         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11525         GL_DepthTest(true);
11526         GL_CullFace(GL_NONE);
11527         R_EntityMatrix(&identitymatrix);
11528
11529         R_Mesh_VertexPointer(vertex3f, 0, 0);
11530         R_Mesh_ColorPointer(NULL, 0, 0);
11531         R_Mesh_ResetTextureState();
11532         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11533
11534         i = surfacelist[0];
11535         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11536                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11537                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11538                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11539
11540         if (VectorCompare(loc->mins, loc->maxs))
11541         {
11542                 VectorSet(size, 2, 2, 2);
11543                 VectorMA(loc->mins, -0.5f, size, mins);
11544         }
11545         else
11546         {
11547                 VectorCopy(loc->mins, mins);
11548                 VectorSubtract(loc->maxs, loc->mins, size);
11549         }
11550
11551         for (i = 0;i < 6*4*3;)
11552                 for (j = 0;j < 3;j++, i++)
11553                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11554
11555         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
11556 }
11557
11558 void R_DrawLocs(void)
11559 {
11560         int index;
11561         cl_locnode_t *loc, *nearestloc;
11562         vec3_t center;
11563         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11564         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11565         {
11566                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11567                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11568         }
11569 }
11570
11571 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11572 {
11573         if (decalsystem->decals)
11574                 Mem_Free(decalsystem->decals);
11575         memset(decalsystem, 0, sizeof(*decalsystem));
11576 }
11577
11578 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)
11579 {
11580         tridecal_t *decal;
11581         tridecal_t *decals;
11582         int i;
11583
11584         // expand or initialize the system
11585         if (decalsystem->maxdecals <= decalsystem->numdecals)
11586         {
11587                 decalsystem_t old = *decalsystem;
11588                 qboolean useshortelements;
11589                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11590                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11591                 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)));
11592                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11593                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11594                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11595                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11596                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11597                 if (decalsystem->numdecals)
11598                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11599                 if (old.decals)
11600                         Mem_Free(old.decals);
11601                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11602                         decalsystem->element3i[i] = i;
11603                 if (useshortelements)
11604                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11605                                 decalsystem->element3s[i] = i;
11606         }
11607
11608         // grab a decal and search for another free slot for the next one
11609         decals = decalsystem->decals;
11610         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11611         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
11612                 ;
11613         decalsystem->freedecal = i;
11614         if (decalsystem->numdecals <= i)
11615                 decalsystem->numdecals = i + 1;
11616
11617         // initialize the decal
11618         decal->lived = 0;
11619         decal->triangleindex = triangleindex;
11620         decal->surfaceindex = surfaceindex;
11621         decal->decalsequence = decalsequence;
11622         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
11623         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
11624         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
11625         decal->color4ub[0][3] = 255;
11626         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
11627         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
11628         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
11629         decal->color4ub[1][3] = 255;
11630         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
11631         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
11632         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
11633         decal->color4ub[2][3] = 255;
11634         decal->vertex3f[0][0] = v0[0];
11635         decal->vertex3f[0][1] = v0[1];
11636         decal->vertex3f[0][2] = v0[2];
11637         decal->vertex3f[1][0] = v1[0];
11638         decal->vertex3f[1][1] = v1[1];
11639         decal->vertex3f[1][2] = v1[2];
11640         decal->vertex3f[2][0] = v2[0];
11641         decal->vertex3f[2][1] = v2[1];
11642         decal->vertex3f[2][2] = v2[2];
11643         decal->texcoord2f[0][0] = t0[0];
11644         decal->texcoord2f[0][1] = t0[1];
11645         decal->texcoord2f[1][0] = t1[0];
11646         decal->texcoord2f[1][1] = t1[1];
11647         decal->texcoord2f[2][0] = t2[0];
11648         decal->texcoord2f[2][1] = t2[1];
11649 }
11650
11651 extern cvar_t cl_decals_bias;
11652 extern cvar_t cl_decals_models;
11653 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11654 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)
11655 {
11656         matrix4x4_t projection;
11657         decalsystem_t *decalsystem;
11658         qboolean dynamic;
11659         dp_model_t *model;
11660         const float *vertex3f;
11661         const msurface_t *surface;
11662         const msurface_t *surfaces;
11663         const int *surfacelist;
11664         const texture_t *texture;
11665         int numtriangles;
11666         int numsurfacelist;
11667         int surfacelistindex;
11668         int surfaceindex;
11669         int triangleindex;
11670         int cornerindex;
11671         int index;
11672         int numpoints;
11673         const int *e;
11674         float localorigin[3];
11675         float localnormal[3];
11676         float localmins[3];
11677         float localmaxs[3];
11678         float localsize;
11679         float v[9][3];
11680         float tc[9][2];
11681         float c[9][4];
11682         //float normal[3];
11683         float planes[6][4];
11684         float f;
11685         float points[2][9][3];
11686         float angles[3];
11687         float temp[3];
11688
11689         decalsystem = &ent->decalsystem;
11690         model = ent->model;
11691         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11692         {
11693                 R_DecalSystem_Reset(&ent->decalsystem);
11694                 return;
11695         }
11696
11697         if (!model->brush.data_nodes && !cl_decals_models.integer)
11698         {
11699                 if (decalsystem->model)
11700                         R_DecalSystem_Reset(decalsystem);
11701                 return;
11702         }
11703
11704         if (decalsystem->model != model)
11705                 R_DecalSystem_Reset(decalsystem);
11706         decalsystem->model = model;
11707
11708         RSurf_ActiveModelEntity(ent, false, false, false);
11709
11710         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11711         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11712         VectorNormalize(localnormal);
11713         localsize = worldsize*rsurface.inversematrixscale;
11714         localmins[0] = localorigin[0] - localsize;
11715         localmins[1] = localorigin[1] - localsize;
11716         localmins[2] = localorigin[2] - localsize;
11717         localmaxs[0] = localorigin[0] + localsize;
11718         localmaxs[1] = localorigin[1] + localsize;
11719         localmaxs[2] = localorigin[2] + localsize;
11720
11721         //VectorCopy(localnormal, planes[4]);
11722         //VectorVectors(planes[4], planes[2], planes[0]);
11723         AnglesFromVectors(angles, localnormal, NULL, false);
11724         AngleVectors(angles, planes[0], planes[2], planes[4]);
11725         VectorNegate(planes[0], planes[1]);
11726         VectorNegate(planes[2], planes[3]);
11727         VectorNegate(planes[4], planes[5]);
11728         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11729         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11730         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11731         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11732         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11733         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11734
11735 #if 1
11736 // works
11737 {
11738         matrix4x4_t forwardprojection;
11739         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11740         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11741 }
11742 #else
11743 // broken
11744 {
11745         float projectionvector[4][3];
11746         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11747         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11748         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11749         projectionvector[0][0] = planes[0][0] * ilocalsize;
11750         projectionvector[0][1] = planes[1][0] * ilocalsize;
11751         projectionvector[0][2] = planes[2][0] * ilocalsize;
11752         projectionvector[1][0] = planes[0][1] * ilocalsize;
11753         projectionvector[1][1] = planes[1][1] * ilocalsize;
11754         projectionvector[1][2] = planes[2][1] * ilocalsize;
11755         projectionvector[2][0] = planes[0][2] * ilocalsize;
11756         projectionvector[2][1] = planes[1][2] * ilocalsize;
11757         projectionvector[2][2] = planes[2][2] * ilocalsize;
11758         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11759         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11760         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11761         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11762 }
11763 #endif
11764
11765         dynamic = model->surfmesh.isanimated;
11766         vertex3f = rsurface.modelvertex3f;
11767         numsurfacelist = model->nummodelsurfaces;
11768         surfacelist = model->sortedmodelsurfaces;
11769         surfaces = model->data_surfaces;
11770         for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11771         {
11772                 surfaceindex = surfacelist[surfacelistindex];
11773                 surface = surfaces + surfaceindex;
11774                 // check cull box first because it rejects more than any other check
11775                 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11776                         continue;
11777                 // skip transparent surfaces
11778                 texture = surface->texture;
11779                 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11780                         continue;
11781                 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11782                         continue;
11783                 numtriangles = surface->num_triangles;
11784                 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
11785                 {
11786                         for (cornerindex = 0;cornerindex < 3;cornerindex++)
11787                         {
11788                                 index = 3*e[cornerindex];
11789                                 VectorCopy(vertex3f + index, v[cornerindex]);
11790                         }
11791                         // cull backfaces
11792                         //TriangleNormal(v[0], v[1], v[2], normal);
11793                         //if (DotProduct(normal, localnormal) < 0.0f)
11794                         //      continue;
11795                         // clip by each of the box planes formed from the projection matrix
11796                         // if anything survives, we emit the decal
11797                         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]);
11798                         if (numpoints < 3)
11799                                 continue;
11800                         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]);
11801                         if (numpoints < 3)
11802                                 continue;
11803                         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]);
11804                         if (numpoints < 3)
11805                                 continue;
11806                         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]);
11807                         if (numpoints < 3)
11808                                 continue;
11809                         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]);
11810                         if (numpoints < 3)
11811                                 continue;
11812                         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]);
11813                         if (numpoints < 3)
11814                                 continue;
11815                         // some part of the triangle survived, so we have to accept it...
11816                         if (dynamic)
11817                         {
11818                                 // dynamic always uses the original triangle
11819                                 numpoints = 3;
11820                                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11821                                 {
11822                                         index = 3*e[cornerindex];
11823                                         VectorCopy(vertex3f + index, v[cornerindex]);
11824                                 }
11825                         }
11826                         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11827                         {
11828                                 // convert vertex positions to texcoords
11829                                 Matrix4x4_Transform(&projection, v[cornerindex], temp);
11830                                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11831                                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11832                                 // calculate distance fade from the projection origin
11833                                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11834                                 f = bound(0.0f, f, 1.0f);
11835                                 c[cornerindex][0] = r * f;
11836                                 c[cornerindex][1] = g * f;
11837                                 c[cornerindex][2] = b * f;
11838                                 c[cornerindex][3] = 1.0f;
11839                                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11840                         }
11841                         if (dynamic)
11842                                 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);
11843                         else
11844                                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11845                                         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);
11846                 }
11847         }
11848 }
11849
11850 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11851 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)
11852 {
11853         int renderentityindex;
11854         float worldmins[3];
11855         float worldmaxs[3];
11856         entity_render_t *ent;
11857
11858         if (!cl_decals_newsystem.integer)
11859                 return;
11860
11861         worldmins[0] = worldorigin[0] - worldsize;
11862         worldmins[1] = worldorigin[1] - worldsize;
11863         worldmins[2] = worldorigin[2] - worldsize;
11864         worldmaxs[0] = worldorigin[0] + worldsize;
11865         worldmaxs[1] = worldorigin[1] + worldsize;
11866         worldmaxs[2] = worldorigin[2] + worldsize;
11867
11868         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11869
11870         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11871         {
11872                 ent = r_refdef.scene.entities[renderentityindex];
11873                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11874                         continue;
11875
11876                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11877         }
11878 }
11879
11880 typedef struct r_decalsystem_splatqueue_s
11881 {
11882         vec3_t worldorigin;
11883         vec3_t worldnormal;
11884         float color[4];
11885         float tcrange[4];
11886         float worldsize;
11887         int decalsequence;
11888 }
11889 r_decalsystem_splatqueue_t;
11890
11891 int r_decalsystem_numqueued = 0;
11892 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11893
11894 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)
11895 {
11896         r_decalsystem_splatqueue_t *queue;
11897
11898         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11899                 return;
11900
11901         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11902         VectorCopy(worldorigin, queue->worldorigin);
11903         VectorCopy(worldnormal, queue->worldnormal);
11904         Vector4Set(queue->color, r, g, b, a);
11905         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11906         queue->worldsize = worldsize;
11907         queue->decalsequence = cl.decalsequence++;
11908 }
11909
11910 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11911 {
11912         int i;
11913         r_decalsystem_splatqueue_t *queue;
11914
11915         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11916                 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);
11917         r_decalsystem_numqueued = 0;
11918 }
11919
11920 extern cvar_t cl_decals_max;
11921 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11922 {
11923         int i;
11924         decalsystem_t *decalsystem = &ent->decalsystem;
11925         int numdecals;
11926         int killsequence;
11927         tridecal_t *decal;
11928         float frametime;
11929         float lifetime;
11930
11931         if (!decalsystem->numdecals)
11932                 return;
11933
11934         if (r_showsurfaces.integer)
11935                 return;
11936
11937         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11938         {
11939                 R_DecalSystem_Reset(decalsystem);
11940                 return;
11941         }
11942
11943         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11944         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11945
11946         if (decalsystem->lastupdatetime)
11947                 frametime = (cl.time - decalsystem->lastupdatetime);
11948         else
11949                 frametime = 0;
11950         decalsystem->lastupdatetime = cl.time;
11951         decal = decalsystem->decals;
11952         numdecals = decalsystem->numdecals;
11953
11954         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11955         {
11956                 if (decal->color4ub[0][3])
11957                 {
11958                         decal->lived += frametime;
11959                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11960                         {
11961                                 memset(decal, 0, sizeof(*decal));
11962                                 if (decalsystem->freedecal > i)
11963                                         decalsystem->freedecal = i;
11964                         }
11965                 }
11966         }
11967         decal = decalsystem->decals;
11968         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
11969                 numdecals--;
11970
11971         // collapse the array by shuffling the tail decals into the gaps
11972         for (;;)
11973         {
11974                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
11975                         decalsystem->freedecal++;
11976                 if (decalsystem->freedecal == numdecals)
11977                         break;
11978                 decal[decalsystem->freedecal] = decal[--numdecals];
11979         }
11980
11981         decalsystem->numdecals = numdecals;
11982
11983         if (numdecals <= 0)
11984         {
11985                 // if there are no decals left, reset decalsystem
11986                 R_DecalSystem_Reset(decalsystem);
11987         }
11988 }
11989
11990 extern skinframe_t *decalskinframe;
11991 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11992 {
11993         int i;
11994         decalsystem_t *decalsystem = &ent->decalsystem;
11995         int numdecals;
11996         tridecal_t *decal;
11997         float faderate;
11998         float alpha;
11999         float *v3f;
12000         float *c4f;
12001         float *t2f;
12002         const int *e;
12003         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12004         int numtris = 0;
12005
12006         numdecals = decalsystem->numdecals;
12007         if (!numdecals)
12008                 return;
12009
12010         if (r_showsurfaces.integer)
12011                 return;
12012
12013         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12014         {
12015                 R_DecalSystem_Reset(decalsystem);
12016                 return;
12017         }
12018
12019         // if the model is static it doesn't matter what value we give for
12020         // wantnormals and wanttangents, so this logic uses only rules applicable
12021         // to a model, knowing that they are meaningless otherwise
12022         if (ent == r_refdef.scene.worldentity)
12023                 RSurf_ActiveWorldEntity();
12024         else
12025                 RSurf_ActiveModelEntity(ent, false, false, false);
12026
12027         decalsystem->lastupdatetime = cl.time;
12028         decal = decalsystem->decals;
12029
12030         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12031
12032         // update vertex positions for animated models
12033         v3f = decalsystem->vertex3f;
12034         c4f = decalsystem->color4f;
12035         t2f = decalsystem->texcoord2f;
12036         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12037         {
12038                 if (!decal->color4ub[0][3])
12039                         continue;
12040
12041                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12042                         continue;
12043
12044                 // update color values for fading decals
12045                 if (decal->lived >= cl_decals_time.value)
12046                 {
12047                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12048                         alpha *= (1.0f/255.0f);
12049                 }
12050                 else
12051                         alpha = 1.0f/255.0f;
12052
12053                 c4f[ 0] = decal->color4ub[0][0] * alpha;
12054                 c4f[ 1] = decal->color4ub[0][1] * alpha;
12055                 c4f[ 2] = decal->color4ub[0][2] * alpha;
12056                 c4f[ 3] = 1;
12057                 c4f[ 4] = decal->color4ub[1][0] * alpha;
12058                 c4f[ 5] = decal->color4ub[1][1] * alpha;
12059                 c4f[ 6] = decal->color4ub[1][2] * alpha;
12060                 c4f[ 7] = 1;
12061                 c4f[ 8] = decal->color4ub[2][0] * alpha;
12062                 c4f[ 9] = decal->color4ub[2][1] * alpha;
12063                 c4f[10] = decal->color4ub[2][2] * alpha;
12064                 c4f[11] = 1;
12065
12066                 t2f[0] = decal->texcoord2f[0][0];
12067                 t2f[1] = decal->texcoord2f[0][1];
12068                 t2f[2] = decal->texcoord2f[1][0];
12069                 t2f[3] = decal->texcoord2f[1][1];
12070                 t2f[4] = decal->texcoord2f[2][0];
12071                 t2f[5] = decal->texcoord2f[2][1];
12072
12073                 // update vertex positions for animated models
12074                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
12075                 {
12076                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12077                         VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
12078                         VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
12079                         VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
12080                 }
12081                 else
12082                 {
12083                         VectorCopy(decal->vertex3f[0], v3f);
12084                         VectorCopy(decal->vertex3f[1], v3f + 3);
12085                         VectorCopy(decal->vertex3f[2], v3f + 6);
12086                 }
12087
12088                 if (r_refdef.fogenabled)
12089                 {
12090                         alpha = RSurf_FogVertex(v3f);
12091                         VectorScale(c4f, alpha, c4f);
12092                         alpha = RSurf_FogVertex(v3f + 3);
12093                         VectorScale(c4f + 4, alpha, c4f + 4);
12094                         alpha = RSurf_FogVertex(v3f + 6);
12095                         VectorScale(c4f + 8, alpha, c4f + 8);
12096                 }
12097
12098                 v3f += 9;
12099                 c4f += 12;
12100                 t2f += 6;
12101                 numtris++;
12102         }
12103
12104         if (numtris > 0)
12105         {
12106                 r_refdef.stats.drawndecals += numtris;
12107
12108                 // now render the decals all at once
12109                 // (this assumes they all use one particle font texture!)
12110                 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);
12111                 R_Mesh_ResetTextureState();
12112                 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
12113                 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
12114                 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
12115                 GL_DepthMask(false);
12116                 GL_DepthRange(0, 1);
12117                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12118                 GL_DepthTest(true);
12119                 GL_CullFace(GL_NONE);
12120                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12121                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
12122                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
12123         }
12124 }
12125
12126 static void R_DrawModelDecals(void)
12127 {
12128         int i, numdecals;
12129
12130         // fade faster when there are too many decals
12131         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12132         for (i = 0;i < r_refdef.scene.numentities;i++)
12133                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12134
12135         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12136         for (i = 0;i < r_refdef.scene.numentities;i++)
12137                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12138                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12139
12140         R_DecalSystem_ApplySplatEntitiesQueue();
12141
12142         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12143         for (i = 0;i < r_refdef.scene.numentities;i++)
12144                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12145
12146         r_refdef.stats.totaldecals += numdecals;
12147
12148         if (r_showsurfaces.integer)
12149                 return;
12150
12151         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12152
12153         for (i = 0;i < r_refdef.scene.numentities;i++)
12154         {
12155                 if (!r_refdef.viewcache.entityvisible[i])
12156                         continue;
12157                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12158                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12159         }
12160 }
12161
12162 extern cvar_t mod_collision_bih;
12163 void R_DrawDebugModel(void)
12164 {
12165         entity_render_t *ent = rsurface.entity;
12166         int i, j, k, l, flagsmask;
12167         const msurface_t *surface;
12168         dp_model_t *model = ent->model;
12169         vec3_t v;
12170
12171         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12172
12173         R_Mesh_ColorPointer(NULL, 0, 0);
12174         R_Mesh_ResetTextureState();
12175         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12176         GL_DepthRange(0, 1);
12177         GL_DepthTest(!r_showdisabledepthtest.integer);
12178         GL_DepthMask(false);
12179         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12180
12181         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12182         {
12183                 int triangleindex;
12184                 int bihleafindex;
12185                 qboolean cullbox = ent == r_refdef.scene.worldentity;
12186                 const q3mbrush_t *brush;
12187                 const bih_t *bih = &model->collision_bih;
12188                 const bih_leaf_t *bihleaf;
12189                 float vertex3f[3][3];
12190                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12191                 cullbox = false;
12192                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12193                 {
12194                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12195                                 continue;
12196                         switch (bihleaf->type)
12197                         {
12198                         case BIH_BRUSH:
12199                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12200                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12201                                 {
12202                                         R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
12203                                         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);
12204                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
12205                                 }
12206                                 break;
12207                         case BIH_COLLISIONTRIANGLE:
12208                                 triangleindex = bihleaf->itemindex;
12209                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12210                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12211                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12212                                 R_Mesh_VertexPointer(vertex3f[0], 0, 0);
12213                                 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);
12214                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, polygonelement3s, 0, 0);
12215                                 break;
12216                         case BIH_RENDERTRIANGLE:
12217                                 triangleindex = bihleaf->itemindex;
12218                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12219                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12220                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12221                                 R_Mesh_VertexPointer(vertex3f[0], 0, 0);
12222                                 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);
12223                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, polygonelement3s, 0, 0);
12224                                 break;
12225                         }
12226                 }
12227         }
12228
12229         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12230
12231         if (r_showtris.integer || r_shownormals.integer)
12232         {
12233                 if (r_showdisabledepthtest.integer)
12234                 {
12235                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12236                         GL_DepthMask(false);
12237                 }
12238                 else
12239                 {
12240                         GL_BlendFunc(GL_ONE, GL_ZERO);
12241                         GL_DepthMask(true);
12242                 }
12243                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12244                 {
12245                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12246                                 continue;
12247                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12248                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12249                         {
12250                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
12251                                 if (r_showtris.value > 0)
12252                                 {
12253                                         if (!rsurface.texture->currentlayers->depthmask)
12254                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12255                                         else if (ent == r_refdef.scene.worldentity)
12256                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12257                                         else
12258                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12259                                         R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
12260                                         R_Mesh_ColorPointer(NULL, 0, 0);
12261                                         R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
12262                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
12263                                         //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
12264                                         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);
12265                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
12266                                         CHECKGLERROR
12267                                 }
12268                                 if (r_shownormals.value < 0)
12269                                 {
12270                                         qglBegin(GL_LINES);
12271                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12272                                         {
12273                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
12274                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12275                                                 qglVertex3f(v[0], v[1], v[2]);
12276                                                 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
12277                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12278                                                 qglVertex3f(v[0], v[1], v[2]);
12279                                         }
12280                                         qglEnd();
12281                                         CHECKGLERROR
12282                                 }
12283                                 if (r_shownormals.value > 0)
12284                                 {
12285                                         qglBegin(GL_LINES);
12286                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12287                                         {
12288                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
12289                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12290                                                 qglVertex3f(v[0], v[1], v[2]);
12291                                                 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
12292                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12293                                                 qglVertex3f(v[0], v[1], v[2]);
12294                                         }
12295                                         qglEnd();
12296                                         CHECKGLERROR
12297                                         qglBegin(GL_LINES);
12298                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12299                                         {
12300                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
12301                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12302                                                 qglVertex3f(v[0], v[1], v[2]);
12303                                                 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
12304                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12305                                                 qglVertex3f(v[0], v[1], v[2]);
12306                                         }
12307                                         qglEnd();
12308                                         CHECKGLERROR
12309                                         qglBegin(GL_LINES);
12310                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12311                                         {
12312                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
12313                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12314                                                 qglVertex3f(v[0], v[1], v[2]);
12315                                                 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
12316                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12317                                                 qglVertex3f(v[0], v[1], v[2]);
12318                                         }
12319                                         qglEnd();
12320                                         CHECKGLERROR
12321                                 }
12322                         }
12323                 }
12324                 rsurface.texture = NULL;
12325         }
12326 }
12327
12328 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
12329 int r_maxsurfacelist = 0;
12330 const msurface_t **r_surfacelist = NULL;
12331 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12332 {
12333         int i, j, endj, flagsmask;
12334         dp_model_t *model = r_refdef.scene.worldmodel;
12335         msurface_t *surfaces;
12336         unsigned char *update;
12337         int numsurfacelist = 0;
12338         if (model == NULL)
12339                 return;
12340
12341         if (r_maxsurfacelist < model->num_surfaces)
12342         {
12343                 r_maxsurfacelist = model->num_surfaces;
12344                 if (r_surfacelist)
12345                         Mem_Free((msurface_t**)r_surfacelist);
12346                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12347         }
12348
12349         RSurf_ActiveWorldEntity();
12350
12351         surfaces = model->data_surfaces;
12352         update = model->brushq1.lightmapupdateflags;
12353
12354         // update light styles on this submodel
12355         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12356         {
12357                 model_brush_lightstyleinfo_t *style;
12358                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12359                 {
12360                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12361                         {
12362                                 int *list = style->surfacelist;
12363                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12364                                 for (j = 0;j < style->numsurfaces;j++)
12365                                         update[list[j]] = true;
12366                         }
12367                 }
12368         }
12369
12370         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12371
12372         if (debug)
12373         {
12374                 R_DrawDebugModel();
12375                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12376                 return;
12377         }
12378
12379         rsurface.uselightmaptexture = false;
12380         rsurface.texture = NULL;
12381         rsurface.rtlight = NULL;
12382         numsurfacelist = 0;
12383         // add visible surfaces to draw list
12384         for (i = 0;i < model->nummodelsurfaces;i++)
12385         {
12386                 j = model->sortedmodelsurfaces[i];
12387                 if (r_refdef.viewcache.world_surfacevisible[j])
12388                         r_surfacelist[numsurfacelist++] = surfaces + j;
12389         }
12390         // update lightmaps if needed
12391         if (model->brushq1.firstrender)
12392         {
12393                 model->brushq1.firstrender = false;
12394                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12395                         if (update[j])
12396                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12397         }
12398         else if (update)
12399         {
12400                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12401                         if (r_refdef.viewcache.world_surfacevisible[j])
12402                                 if (update[j])
12403                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12404         }
12405         // don't do anything if there were no surfaces
12406         if (!numsurfacelist)
12407         {
12408                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12409                 return;
12410         }
12411         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12412         GL_AlphaTest(false);
12413
12414         // add to stats if desired
12415         if (r_speeds.integer && !skysurfaces && !depthonly)
12416         {
12417                 r_refdef.stats.world_surfaces += numsurfacelist;
12418                 for (j = 0;j < numsurfacelist;j++)
12419                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
12420         }
12421
12422         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12423 }
12424
12425 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12426 {
12427         int i, j, endj, flagsmask;
12428         dp_model_t *model = ent->model;
12429         msurface_t *surfaces;
12430         unsigned char *update;
12431         int numsurfacelist = 0;
12432         if (model == NULL)
12433                 return;
12434
12435         if (r_maxsurfacelist < model->num_surfaces)
12436         {
12437                 r_maxsurfacelist = model->num_surfaces;
12438                 if (r_surfacelist)
12439                         Mem_Free((msurface_t **)r_surfacelist);
12440                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12441         }
12442
12443         // if the model is static it doesn't matter what value we give for
12444         // wantnormals and wanttangents, so this logic uses only rules applicable
12445         // to a model, knowing that they are meaningless otherwise
12446         if (ent == r_refdef.scene.worldentity)
12447                 RSurf_ActiveWorldEntity();
12448         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12449                 RSurf_ActiveModelEntity(ent, false, false, false);
12450         else if (prepass)
12451                 RSurf_ActiveModelEntity(ent, true, true, true);
12452         else if (depthonly)
12453         {
12454                 switch (vid.renderpath)
12455                 {
12456                 case RENDERPATH_GL20:
12457                 case RENDERPATH_CGGL:
12458                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12459                         break;
12460                 case RENDERPATH_GL13:
12461                 case RENDERPATH_GL11:
12462                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12463                         break;
12464                 }
12465         }
12466         else
12467         {
12468                 switch (vid.renderpath)
12469                 {
12470                 case RENDERPATH_GL20:
12471                 case RENDERPATH_CGGL:
12472                         RSurf_ActiveModelEntity(ent, true, true, false);
12473                         break;
12474                 case RENDERPATH_GL13:
12475                 case RENDERPATH_GL11:
12476                         RSurf_ActiveModelEntity(ent, true, false, false);
12477                         break;
12478                 }
12479         }
12480
12481         surfaces = model->data_surfaces;
12482         update = model->brushq1.lightmapupdateflags;
12483
12484         // update light styles
12485         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12486         {
12487                 model_brush_lightstyleinfo_t *style;
12488                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12489                 {
12490                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12491                         {
12492                                 int *list = style->surfacelist;
12493                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12494                                 for (j = 0;j < style->numsurfaces;j++)
12495                                         update[list[j]] = true;
12496                         }
12497                 }
12498         }
12499
12500         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12501
12502         if (debug)
12503         {
12504                 R_DrawDebugModel();
12505                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12506                 return;
12507         }
12508
12509         rsurface.uselightmaptexture = false;
12510         rsurface.texture = NULL;
12511         rsurface.rtlight = NULL;
12512         numsurfacelist = 0;
12513         // add visible surfaces to draw list
12514         for (i = 0;i < model->nummodelsurfaces;i++)
12515                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12516         // don't do anything if there were no surfaces
12517         if (!numsurfacelist)
12518         {
12519                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12520                 return;
12521         }
12522         // update lightmaps if needed
12523         if (update)
12524         {
12525                 int updated = 0;
12526                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12527                 {
12528                         if (update[j])
12529                         {
12530                                 updated++;
12531                                 R_BuildLightMap(ent, surfaces + j);
12532                         }
12533                 }
12534         }
12535         if (update)
12536                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12537                         if (update[j])
12538                                 R_BuildLightMap(ent, surfaces + j);
12539         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12540         GL_AlphaTest(false);
12541
12542         // add to stats if desired
12543         if (r_speeds.integer && !skysurfaces && !depthonly)
12544         {
12545                 r_refdef.stats.entities_surfaces += numsurfacelist;
12546                 for (j = 0;j < numsurfacelist;j++)
12547                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
12548         }
12549
12550         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12551 }
12552
12553 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12554 {
12555         static texture_t texture;
12556         static msurface_t surface;
12557         const msurface_t *surfacelist = &surface;
12558
12559         // fake enough texture and surface state to render this geometry
12560
12561         texture.update_lastrenderframe = -1; // regenerate this texture
12562         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12563         texture.currentskinframe = skinframe;
12564         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12565         texture.offsetmapping = OFFSETMAPPING_OFF;
12566         texture.offsetscale = 1;
12567         texture.specularscalemod = 1;
12568         texture.specularpowermod = 1;
12569
12570         surface.texture = &texture;
12571         surface.num_triangles = numtriangles;
12572         surface.num_firsttriangle = firsttriangle;
12573         surface.num_vertices = numvertices;
12574         surface.num_firstvertex = firstvertex;
12575
12576         // now render it
12577         rsurface.texture = R_GetCurrentTexture(surface.texture);
12578         rsurface.uselightmaptexture = false;
12579         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12580 }
12581
12582 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)
12583 {
12584         static msurface_t surface;
12585         const msurface_t *surfacelist = &surface;
12586
12587         // fake enough texture and surface state to render this geometry
12588
12589         surface.texture = texture;
12590         surface.num_triangles = numtriangles;
12591         surface.num_firsttriangle = firsttriangle;
12592         surface.num_vertices = numvertices;
12593         surface.num_firstvertex = firstvertex;
12594
12595         // now render it
12596         rsurface.texture = R_GetCurrentTexture(surface.texture);
12597         rsurface.uselightmaptexture = false;
12598         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12599 }