]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
attempting workaround for coord rounding incompatibilities between GL_ARB_texture_gat...
[divverent/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28
29 mempool_t *r_main_mempool;
30 rtexturepool_t *r_main_texturepool;
31
32 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
33
34 static qboolean r_loadnormalmap;
35 static qboolean r_loadgloss;
36 qboolean r_loadfog;
37 static qboolean r_loaddds;
38 static qboolean r_savedds;
39
40 //
41 // screen size info
42 //
43 r_refdef_t r_refdef;
44
45 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
46 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
47 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
48 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
49 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
50 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
51 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
52 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
53
54 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
55 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
56 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
57 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
58 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
59
60 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
61 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
62 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
63 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
64 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
65 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
66 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
67 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
68 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
69 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
70 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
71 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
72 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
73 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
74 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
75 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
76 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
77 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
78 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
79 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
80 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
81 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
82 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
83 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
84 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
85 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
86 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
87 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
88 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
89 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
90 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
91 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
92 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
93 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
94 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
95 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
96 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
97 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
98 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
99 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
100 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
101 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
102 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
103 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
104
105 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
106 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
107 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
108 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
109 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
110 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
111 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
112 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
113
114 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
115 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
116
117 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
118 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
119 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
120 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
121 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
122
123 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
124 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
125 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
126
127 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
128 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
129 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
130 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
131 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
132 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
133 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
134 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
135 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
136
137 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
138 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
139 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
140 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
141 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
142
143 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
144 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
145 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
146 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
147
148 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
149 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
150 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
151 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
152 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
153 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
154 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
155
156 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
157 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
158 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
159 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
160
161 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
162
163 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
164
165 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
166
167 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
168 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
169 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
170 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
171 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
172 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
173 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
174 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "16", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
175
176 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
177
178 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "1", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
179
180 extern cvar_t v_glslgamma;
181
182 extern qboolean v_flipped_state;
183
184 static struct r_bloomstate_s
185 {
186         qboolean enabled;
187         qboolean hdr;
188
189         int bloomwidth, bloomheight;
190
191         int screentexturewidth, screentextureheight;
192         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
193
194         int bloomtexturewidth, bloomtextureheight;
195         rtexture_t *texture_bloom;
196
197         // arrays for rendering the screen passes
198         float screentexcoord2f[8];
199         float bloomtexcoord2f[8];
200         float offsettexcoord2f[8];
201
202         r_viewport_t viewport;
203 }
204 r_bloomstate;
205
206 r_waterstate_t r_waterstate;
207
208 /// shadow volume bsp struct with automatically growing nodes buffer
209 svbsp_t r_svbsp;
210
211 rtexture_t *r_texture_blanknormalmap;
212 rtexture_t *r_texture_white;
213 rtexture_t *r_texture_grey128;
214 rtexture_t *r_texture_black;
215 rtexture_t *r_texture_notexture;
216 rtexture_t *r_texture_whitecube;
217 rtexture_t *r_texture_normalizationcube;
218 rtexture_t *r_texture_fogattenuation;
219 rtexture_t *r_texture_gammaramps;
220 unsigned int r_texture_gammaramps_serial;
221 //rtexture_t *r_texture_fogintensity;
222 rtexture_t *r_texture_reflectcube;
223
224 // TODO: hash lookups?
225 typedef struct cubemapinfo_s
226 {
227         char basename[64];
228         rtexture_t *texture;
229 }
230 cubemapinfo_t;
231
232 int r_texture_numcubemaps;
233 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
234
235 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
236 unsigned int r_numqueries;
237 unsigned int r_maxqueries;
238
239 typedef struct r_qwskincache_s
240 {
241         char name[MAX_QPATH];
242         skinframe_t *skinframe;
243 }
244 r_qwskincache_t;
245
246 static r_qwskincache_t *r_qwskincache;
247 static int r_qwskincache_size;
248
249 /// vertex coordinates for a quad that covers the screen exactly
250 const float r_screenvertex3f[12] =
251 {
252         0, 0, 0,
253         1, 0, 0,
254         1, 1, 0,
255         0, 1, 0
256 };
257
258 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
259 {
260         int i;
261         for (i = 0;i < verts;i++)
262         {
263                 out[0] = in[0] * r;
264                 out[1] = in[1] * g;
265                 out[2] = in[2] * b;
266                 out[3] = in[3];
267                 in += 4;
268                 out += 4;
269         }
270 }
271
272 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
273 {
274         int i;
275         for (i = 0;i < verts;i++)
276         {
277                 out[0] = r;
278                 out[1] = g;
279                 out[2] = b;
280                 out[3] = a;
281                 out += 4;
282         }
283 }
284
285 // FIXME: move this to client?
286 void FOG_clear(void)
287 {
288         if (gamemode == GAME_NEHAHRA)
289         {
290                 Cvar_Set("gl_fogenable", "0");
291                 Cvar_Set("gl_fogdensity", "0.2");
292                 Cvar_Set("gl_fogred", "0.3");
293                 Cvar_Set("gl_foggreen", "0.3");
294                 Cvar_Set("gl_fogblue", "0.3");
295         }
296         r_refdef.fog_density = 0;
297         r_refdef.fog_red = 0;
298         r_refdef.fog_green = 0;
299         r_refdef.fog_blue = 0;
300         r_refdef.fog_alpha = 1;
301         r_refdef.fog_start = 0;
302         r_refdef.fog_end = 16384;
303         r_refdef.fog_height = 1<<30;
304         r_refdef.fog_fadedepth = 128;
305 }
306
307 static void R_BuildBlankTextures(void)
308 {
309         unsigned char data[4];
310         data[2] = 128; // normal X
311         data[1] = 128; // normal Y
312         data[0] = 255; // normal Z
313         data[3] = 128; // height
314         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
315         data[0] = 255;
316         data[1] = 255;
317         data[2] = 255;
318         data[3] = 255;
319         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
320         data[0] = 128;
321         data[1] = 128;
322         data[2] = 128;
323         data[3] = 255;
324         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
325         data[0] = 0;
326         data[1] = 0;
327         data[2] = 0;
328         data[3] = 255;
329         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
330 }
331
332 static void R_BuildNoTexture(void)
333 {
334         int x, y;
335         unsigned char pix[16][16][4];
336         // this makes a light grey/dark grey checkerboard texture
337         for (y = 0;y < 16;y++)
338         {
339                 for (x = 0;x < 16;x++)
340                 {
341                         if ((y < 8) ^ (x < 8))
342                         {
343                                 pix[y][x][0] = 128;
344                                 pix[y][x][1] = 128;
345                                 pix[y][x][2] = 128;
346                                 pix[y][x][3] = 255;
347                         }
348                         else
349                         {
350                                 pix[y][x][0] = 64;
351                                 pix[y][x][1] = 64;
352                                 pix[y][x][2] = 64;
353                                 pix[y][x][3] = 255;
354                         }
355                 }
356         }
357         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
358 }
359
360 static void R_BuildWhiteCube(void)
361 {
362         unsigned char data[6*1*1*4];
363         memset(data, 255, sizeof(data));
364         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
365 }
366
367 static void R_BuildNormalizationCube(void)
368 {
369         int x, y, side;
370         vec3_t v;
371         vec_t s, t, intensity;
372 #define NORMSIZE 64
373         unsigned char *data;
374         data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
375         for (side = 0;side < 6;side++)
376         {
377                 for (y = 0;y < NORMSIZE;y++)
378                 {
379                         for (x = 0;x < NORMSIZE;x++)
380                         {
381                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
382                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
383                                 switch(side)
384                                 {
385                                 default:
386                                 case 0:
387                                         v[0] = 1;
388                                         v[1] = -t;
389                                         v[2] = -s;
390                                         break;
391                                 case 1:
392                                         v[0] = -1;
393                                         v[1] = -t;
394                                         v[2] = s;
395                                         break;
396                                 case 2:
397                                         v[0] = s;
398                                         v[1] = 1;
399                                         v[2] = t;
400                                         break;
401                                 case 3:
402                                         v[0] = s;
403                                         v[1] = -1;
404                                         v[2] = -t;
405                                         break;
406                                 case 4:
407                                         v[0] = s;
408                                         v[1] = -t;
409                                         v[2] = 1;
410                                         break;
411                                 case 5:
412                                         v[0] = -s;
413                                         v[1] = -t;
414                                         v[2] = -1;
415                                         break;
416                                 }
417                                 intensity = 127.0f / sqrt(DotProduct(v, v));
418                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
419                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
420                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
421                                 data[((side*64+y)*64+x)*4+3] = 255;
422                         }
423                 }
424         }
425         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
426         Mem_Free(data);
427 }
428
429 static void R_BuildFogTexture(void)
430 {
431         int x, b;
432 #define FOGWIDTH 256
433         unsigned char data1[FOGWIDTH][4];
434         //unsigned char data2[FOGWIDTH][4];
435         double d, r, alpha;
436
437         r_refdef.fogmasktable_start = r_refdef.fog_start;
438         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
439         r_refdef.fogmasktable_range = r_refdef.fogrange;
440         r_refdef.fogmasktable_density = r_refdef.fog_density;
441
442         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
443         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
444         {
445                 d = (x * r - r_refdef.fogmasktable_start);
446                 if(developer_extra.integer)
447                         Con_DPrintf("%f ", d);
448                 d = max(0, d);
449                 if (r_fog_exp2.integer)
450                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
451                 else
452                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
453                 if(developer_extra.integer)
454                         Con_DPrintf(" : %f ", alpha);
455                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
456                 if(developer_extra.integer)
457                         Con_DPrintf(" = %f\n", alpha);
458                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
459         }
460
461         for (x = 0;x < FOGWIDTH;x++)
462         {
463                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
464                 data1[x][0] = b;
465                 data1[x][1] = b;
466                 data1[x][2] = b;
467                 data1[x][3] = 255;
468                 //data2[x][0] = 255 - b;
469                 //data2[x][1] = 255 - b;
470                 //data2[x][2] = 255 - b;
471                 //data2[x][3] = 255;
472         }
473         if (r_texture_fogattenuation)
474         {
475                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
476                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
477         }
478         else
479         {
480                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, NULL);
481                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
482         }
483 }
484
485 //=======================================================================================================================================================
486
487 static const char *builtinshaderstring =
488 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
489 "// written by Forest 'LordHavoc' Hale\n"
490 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
491 "\n"
492 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
493 "# define USEFOG\n"
494 "#endif\n"
495 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
496 "#define USELIGHTMAP\n"
497 "#endif\n"
498 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
499 "#define USEEYEVECTOR\n"
500 "#endif\n"
501 "\n"
502 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
503 "# extension GL_ARB_texture_rectangle : enable\n"
504 "#endif\n"
505 "\n"
506 "#ifdef USESHADOWMAP2D\n"
507 "# ifdef GL_EXT_gpu_shader4\n"
508 "#   extension GL_EXT_gpu_shader4 : enable\n"
509 "# endif\n"
510 "# ifdef GL_ARB_texture_gather\n"
511 "#   extension GL_ARB_texture_gather : enable\n"
512 "# else\n"
513 "#   ifdef GL_AMD_texture_texture4\n"
514 "#     extension GL_AMD_texture_texture4 : enable\n"
515 "#   endif\n"
516 "# endif\n"
517 "#endif\n"
518 "\n"
519 "#ifdef USESHADOWMAPCUBE\n"
520 "# extension GL_EXT_gpu_shader4 : enable\n"
521 "#endif\n"
522 "\n"
523 "//#ifdef USESHADOWSAMPLER\n"
524 "//# extension GL_ARB_shadow : enable\n"
525 "//#endif\n"
526 "\n"
527 "//#ifdef __GLSL_CG_DATA_TYPES\n"
528 "//# define myhalf half\n"
529 "//# define myhalf2 half2\n"
530 "//# define myhalf3 half3\n"
531 "//# define myhalf4 half4\n"
532 "//#else\n"
533 "# define myhalf float\n"
534 "# define myhalf2 vec2\n"
535 "# define myhalf3 vec3\n"
536 "# define myhalf4 vec4\n"
537 "//#endif\n"
538 "\n"
539 "#ifdef VERTEX_SHADER\n"
540 "uniform mat4 ModelViewProjectionMatrix;\n"
541 "#endif\n"
542 "\n"
543 "#ifdef MODE_DEPTH_OR_SHADOW\n"
544 "#ifdef VERTEX_SHADER\n"
545 "void main(void)\n"
546 "{\n"
547 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
548 "}\n"
549 "#endif\n"
550 "#else // !MODE_DEPTH_ORSHADOW\n"
551 "\n"
552 "\n"
553 "\n"
554 "\n"
555 "#ifdef MODE_SHOWDEPTH\n"
556 "#ifdef VERTEX_SHADER\n"
557 "void main(void)\n"
558 "{\n"
559 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
560 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
561 "}\n"
562 "#endif\n"
563 "\n"
564 "#ifdef FRAGMENT_SHADER\n"
565 "void main(void)\n"
566 "{\n"
567 "       gl_FragColor = gl_Color;\n"
568 "}\n"
569 "#endif\n"
570 "#else // !MODE_SHOWDEPTH\n"
571 "\n"
572 "\n"
573 "\n"
574 "\n"
575 "#ifdef MODE_POSTPROCESS\n"
576 "varying vec2 TexCoord1;\n"
577 "varying vec2 TexCoord2;\n"
578 "\n"
579 "#ifdef VERTEX_SHADER\n"
580 "void main(void)\n"
581 "{\n"
582 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
583 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
584 "#ifdef USEBLOOM\n"
585 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
586 "#endif\n"
587 "}\n"
588 "#endif\n"
589 "\n"
590 "#ifdef FRAGMENT_SHADER\n"
591 "uniform sampler2D Texture_First;\n"
592 "#ifdef USEBLOOM\n"
593 "uniform sampler2D Texture_Second;\n"
594 "#endif\n"
595 "#ifdef USEGAMMARAMPS\n"
596 "uniform sampler2D Texture_GammaRamps;\n"
597 "#endif\n"
598 "#ifdef USESATURATION\n"
599 "uniform float Saturation;\n"
600 "#endif\n"
601 "#ifdef USEVIEWTINT\n"
602 "uniform vec4 ViewTintColor;\n"
603 "#endif\n"
604 "//uncomment these if you want to use them:\n"
605 "uniform vec4 UserVec1;\n"
606 "// uniform vec4 UserVec2;\n"
607 "// uniform vec4 UserVec3;\n"
608 "// uniform vec4 UserVec4;\n"
609 "// uniform float ClientTime;\n"
610 "uniform vec2 PixelSize;\n"
611 "void main(void)\n"
612 "{\n"
613 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
614 "#ifdef USEBLOOM\n"
615 "       gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
616 "#endif\n"
617 "#ifdef USEVIEWTINT\n"
618 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
619 "#endif\n"
620 "\n"
621 "#ifdef USEPOSTPROCESSING\n"
622 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
623 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
624 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
625 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
626 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
627 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
628 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
629 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
630 "#endif\n"
631 "\n"
632 "#ifdef USESATURATION\n"
633 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
634 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
635 "       //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
636 "       gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
637 "#endif\n"
638 "\n"
639 "#ifdef USEGAMMARAMPS\n"
640 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
641 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
642 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
643 "#endif\n"
644 "}\n"
645 "#endif\n"
646 "#else // !MODE_POSTPROCESS\n"
647 "\n"
648 "\n"
649 "\n"
650 "\n"
651 "#ifdef MODE_GENERIC\n"
652 "#ifdef USEDIFFUSE\n"
653 "varying vec2 TexCoord1;\n"
654 "#endif\n"
655 "#ifdef USESPECULAR\n"
656 "varying vec2 TexCoord2;\n"
657 "#endif\n"
658 "#ifdef VERTEX_SHADER\n"
659 "void main(void)\n"
660 "{\n"
661 "       gl_FrontColor = gl_Color;\n"
662 "#ifdef USEDIFFUSE\n"
663 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
664 "#endif\n"
665 "#ifdef USESPECULAR\n"
666 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
667 "#endif\n"
668 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
669 "}\n"
670 "#endif\n"
671 "\n"
672 "#ifdef FRAGMENT_SHADER\n"
673 "#ifdef USEDIFFUSE\n"
674 "uniform sampler2D Texture_First;\n"
675 "#endif\n"
676 "#ifdef USESPECULAR\n"
677 "uniform sampler2D Texture_Second;\n"
678 "#endif\n"
679 "\n"
680 "void main(void)\n"
681 "{\n"
682 "       gl_FragColor = gl_Color;\n"
683 "#ifdef USEDIFFUSE\n"
684 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
685 "#endif\n"
686 "\n"
687 "#ifdef USESPECULAR\n"
688 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
689 "# ifdef USECOLORMAPPING\n"
690 "       gl_FragColor *= tex2;\n"
691 "# endif\n"
692 "# ifdef USEGLOW\n"
693 "       gl_FragColor += tex2;\n"
694 "# endif\n"
695 "# ifdef USEVERTEXTEXTUREBLEND\n"
696 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
697 "# endif\n"
698 "#endif\n"
699 "}\n"
700 "#endif\n"
701 "#else // !MODE_GENERIC\n"
702 "\n"
703 "\n"
704 "\n"
705 "\n"
706 "#ifdef MODE_BLOOMBLUR\n"
707 "varying TexCoord;\n"
708 "#ifdef VERTEX_SHADER\n"
709 "void main(void)\n"
710 "{\n"
711 "       gl_FrontColor = gl_Color;\n"
712 "       TexCoord = gl_MultiTexCoord0.xy;\n"
713 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
714 "}\n"
715 "#endif\n"
716 "\n"
717 "#ifdef FRAGMENT_SHADER\n"
718 "uniform sampler2D Texture_First;\n"
719 "uniform vec4 BloomBlur_Parameters;\n"
720 "\n"
721 "void main(void)\n"
722 "{\n"
723 "       int i;\n"
724 "       vec2 tc = TexCoord;\n"
725 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
726 "       tc += BloomBlur_Parameters.xy;\n"
727 "       for (i = 1;i < SAMPLES;i++)\n"
728 "       {\n"
729 "               color += texture2D(Texture_First, tc).rgb;\n"
730 "               tc += BloomBlur_Parameters.xy;\n"
731 "       }\n"
732 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
733 "}\n"
734 "#endif\n"
735 "#else // !MODE_BLOOMBLUR\n"
736 "#ifdef MODE_REFRACTION\n"
737 "varying vec2 TexCoord;\n"
738 "varying vec4 ModelViewProjectionPosition;\n"
739 "uniform mat4 TexMatrix;\n"
740 "#ifdef VERTEX_SHADER\n"
741 "\n"
742 "void main(void)\n"
743 "{\n"
744 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
745 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
746 "       ModelViewProjectionPosition = gl_Position;\n"
747 "}\n"
748 "#endif\n"
749 "\n"
750 "#ifdef FRAGMENT_SHADER\n"
751 "uniform sampler2D Texture_Normal;\n"
752 "uniform sampler2D Texture_Refraction;\n"
753 "uniform sampler2D Texture_Reflection;\n"
754 "\n"
755 "uniform vec4 DistortScaleRefractReflect;\n"
756 "uniform vec4 ScreenScaleRefractReflect;\n"
757 "uniform vec4 ScreenCenterRefractReflect;\n"
758 "uniform vec4 RefractColor;\n"
759 "uniform vec4 ReflectColor;\n"
760 "uniform float ReflectFactor;\n"
761 "uniform float ReflectOffset;\n"
762 "\n"
763 "void main(void)\n"
764 "{\n"
765 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
766 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
767 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
768 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
769 "       // FIXME temporary hack to detect the case that the reflection\n"
770 "       // gets blackened at edges due to leaving the area that contains actual\n"
771 "       // content.\n"
772 "       // Remove this 'ack once we have a better way to stop this thing from\n"
773 "       // 'appening.\n"
774 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
775 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
776 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
777 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
778 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
779 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
780 "}\n"
781 "#endif\n"
782 "#else // !MODE_REFRACTION\n"
783 "\n"
784 "\n"
785 "\n"
786 "\n"
787 "#ifdef MODE_WATER\n"
788 "varying vec2 TexCoord;\n"
789 "varying vec3 EyeVector;\n"
790 "varying vec4 ModelViewProjectionPosition;\n"
791 "#ifdef VERTEX_SHADER\n"
792 "uniform vec3 EyePosition;\n"
793 "uniform mat4 TexMatrix;\n"
794 "\n"
795 "void main(void)\n"
796 "{\n"
797 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
798 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
799 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
800 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
801 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
802 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
803 "       ModelViewProjectionPosition = gl_Position;\n"
804 "}\n"
805 "#endif\n"
806 "\n"
807 "#ifdef FRAGMENT_SHADER\n"
808 "uniform sampler2D Texture_Normal;\n"
809 "uniform sampler2D Texture_Refraction;\n"
810 "uniform sampler2D Texture_Reflection;\n"
811 "\n"
812 "uniform vec4 DistortScaleRefractReflect;\n"
813 "uniform vec4 ScreenScaleRefractReflect;\n"
814 "uniform vec4 ScreenCenterRefractReflect;\n"
815 "uniform vec4 RefractColor;\n"
816 "uniform vec4 ReflectColor;\n"
817 "uniform float ReflectFactor;\n"
818 "uniform float ReflectOffset;\n"
819 "\n"
820 "void main(void)\n"
821 "{\n"
822 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
823 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
824 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
825 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
826 "       vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
827 "       // FIXME temporary hack to detect the case that the reflection\n"
828 "       // gets blackened at edges due to leaving the area that contains actual\n"
829 "       // content.\n"
830 "       // Remove this 'ack once we have a better way to stop this thing from\n"
831 "       // 'appening.\n"
832 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
833 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
834 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
835 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
836 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
837 "       f       = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
838 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
839 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
840 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
841 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
842 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
843 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
844 "}\n"
845 "#endif\n"
846 "#else // !MODE_WATER\n"
847 "\n"
848 "\n"
849 "\n"
850 "\n"
851 "// common definitions between vertex shader and fragment shader:\n"
852 "\n"
853 "varying vec2 TexCoord;\n"
854 "#ifdef USEVERTEXTEXTUREBLEND\n"
855 "varying vec2 TexCoord2;\n"
856 "#endif\n"
857 "#ifdef USELIGHTMAP\n"
858 "varying vec2 TexCoordLightmap;\n"
859 "#endif\n"
860 "\n"
861 "#ifdef MODE_LIGHTSOURCE\n"
862 "varying vec3 CubeVector;\n"
863 "#endif\n"
864 "\n"
865 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
866 "varying vec3 LightVector;\n"
867 "#endif\n"
868 "\n"
869 "#ifdef USEEYEVECTOR\n"
870 "varying vec3 EyeVector;\n"
871 "#endif\n"
872 "#ifdef USEFOG\n"
873 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
874 "#endif\n"
875 "\n"
876 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
877 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
878 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
879 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
880 "#endif\n"
881 "\n"
882 "#ifdef USEREFLECTION\n"
883 "varying vec4 ModelViewProjectionPosition;\n"
884 "#endif\n"
885 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
886 "uniform vec3 LightPosition;\n"
887 "varying vec4 ModelViewPosition;\n"
888 "#endif\n"
889 "\n"
890 "#ifdef MODE_LIGHTSOURCE\n"
891 "uniform vec3 LightPosition;\n"
892 "#endif\n"
893 "uniform vec3 EyePosition;\n"
894 "#ifdef MODE_LIGHTDIRECTION\n"
895 "uniform vec3 LightDir;\n"
896 "#endif\n"
897 "uniform vec4 FogPlane;\n"
898 "\n"
899 "#ifdef USESHADOWMAPORTHO\n"
900 "varying vec3 ShadowMapTC;\n"
901 "#endif\n"
902 "\n"
903 "\n"
904 "\n"
905 "\n"
906 "\n"
907 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
908 "\n"
909 "// fragment shader specific:\n"
910 "#ifdef FRAGMENT_SHADER\n"
911 "\n"
912 "uniform sampler2D Texture_Normal;\n"
913 "uniform sampler2D Texture_Color;\n"
914 "uniform sampler2D Texture_Gloss;\n"
915 "#ifdef USEGLOW\n"
916 "uniform sampler2D Texture_Glow;\n"
917 "#endif\n"
918 "#ifdef USEVERTEXTEXTUREBLEND\n"
919 "uniform sampler2D Texture_SecondaryNormal;\n"
920 "uniform sampler2D Texture_SecondaryColor;\n"
921 "uniform sampler2D Texture_SecondaryGloss;\n"
922 "#ifdef USEGLOW\n"
923 "uniform sampler2D Texture_SecondaryGlow;\n"
924 "#endif\n"
925 "#endif\n"
926 "#ifdef USECOLORMAPPING\n"
927 "uniform sampler2D Texture_Pants;\n"
928 "uniform sampler2D Texture_Shirt;\n"
929 "#endif\n"
930 "#ifdef USEFOG\n"
931 "uniform sampler2D Texture_FogMask;\n"
932 "#endif\n"
933 "#ifdef USELIGHTMAP\n"
934 "uniform sampler2D Texture_Lightmap;\n"
935 "#endif\n"
936 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
937 "uniform sampler2D Texture_Deluxemap;\n"
938 "#endif\n"
939 "#ifdef USEREFLECTION\n"
940 "uniform sampler2D Texture_Reflection;\n"
941 "#endif\n"
942 "\n"
943 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
944 "uniform sampler2D Texture_ScreenDepth;\n"
945 "uniform sampler2D Texture_ScreenNormalMap;\n"
946 "#endif\n"
947 "#ifdef USEDEFERREDLIGHTMAP\n"
948 "uniform sampler2D Texture_ScreenDiffuse;\n"
949 "uniform sampler2D Texture_ScreenSpecular;\n"
950 "#endif\n"
951 "\n"
952 "uniform myhalf3 Color_Pants;\n"
953 "uniform myhalf3 Color_Shirt;\n"
954 "uniform myhalf3 FogColor;\n"
955 "\n"
956 "#ifdef USEFOG\n"
957 "uniform float FogRangeRecip;\n"
958 "uniform float FogPlaneViewDist;\n"
959 "uniform float FogHeightFade;\n"
960 "float FogVertex(void)\n"
961 "{\n"
962 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
963 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
964 "       float fogfrac;\n"
965 "#ifdef USEFOGOUTSIDE\n"
966 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
967 "#else\n"
968 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
969 "#endif\n"
970 "       return float(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
971 "}\n"
972 "#endif\n"
973 "\n"
974 "#ifdef USEOFFSETMAPPING\n"
975 "uniform float OffsetMapping_Scale;\n"
976 "vec2 OffsetMapping(vec2 TexCoord)\n"
977 "{\n"
978 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
979 "       // 14 sample relief mapping: linear search and then binary search\n"
980 "       // this basically steps forward a small amount repeatedly until it finds\n"
981 "       // itself inside solid, then jitters forward and back using decreasing\n"
982 "       // amounts to find the impact\n"
983 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
984 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
985 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
986 "       vec3 RT = vec3(TexCoord, 1);\n"
987 "       OffsetVector *= 0.1;\n"
988 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
989 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
990 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
991 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
992 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
993 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
994 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
995 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
996 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
997 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
998 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
999 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1000 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1001 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1002 "       return RT.xy;\n"
1003 "#else\n"
1004 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1005 "       // this basically moves forward the full distance, and then backs up based\n"
1006 "       // on height of samples\n"
1007 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1008 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1009 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1010 "       TexCoord += OffsetVector;\n"
1011 "       OffsetVector *= 0.333;\n"
1012 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1013 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1014 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1015 "       return TexCoord;\n"
1016 "#endif\n"
1017 "}\n"
1018 "#endif // USEOFFSETMAPPING\n"
1019 "\n"
1020 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1021 "uniform sampler2D Texture_Attenuation;\n"
1022 "uniform samplerCube Texture_Cube;\n"
1023 "#endif\n"
1024 "\n"
1025 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1026 "\n"
1027 "#ifdef USESHADOWMAPRECT\n"
1028 "# ifdef USESHADOWSAMPLER\n"
1029 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1030 "# else\n"
1031 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1032 "# endif\n"
1033 "#endif\n"
1034 "\n"
1035 "#ifdef USESHADOWMAP2D\n"
1036 "# ifdef USESHADOWSAMPLER\n"
1037 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1038 "# else\n"
1039 "uniform sampler2D Texture_ShadowMap2D;\n"
1040 "# endif\n"
1041 "#endif\n"
1042 "\n"
1043 "#ifdef USESHADOWMAPVSDCT\n"
1044 "uniform samplerCube Texture_CubeProjection;\n"
1045 "#endif\n"
1046 "\n"
1047 "#ifdef USESHADOWMAPCUBE\n"
1048 "# ifdef USESHADOWSAMPLER\n"
1049 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1050 "# else\n"
1051 "uniform samplerCube Texture_ShadowMapCube;\n"
1052 "# endif\n"
1053 "#endif\n"
1054 "\n"
1055 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1056 "uniform vec2 ShadowMap_TextureScale;\n"
1057 "uniform vec4 ShadowMap_Parameters;\n"
1058 "#endif\n"
1059 "\n"
1060 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1061 "# ifdef USESHADOWMAPORTHO\n"
1062 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1063 "# else\n"
1064 "#  ifdef USESHADOWMAPVSDCT\n"
1065 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1066 "{\n"
1067 "       vec3 adir = abs(dir);\n"
1068 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1069 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1070 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1071 "}\n"
1072 "#  else\n"
1073 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1074 "{\n"
1075 "       vec3 adir = abs(dir);\n"
1076 "       float ma = adir.z;\n"
1077 "       vec4 proj = vec4(dir, 2.5);\n"
1078 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1079 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1080 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1081 "       return vec3(proj.xy * aparams.x + vec2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1082 "}\n"
1083 "#  endif\n"
1084 "# endif\n"
1085 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1086 "\n"
1087 "#ifdef USESHADOWMAPCUBE\n"
1088 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1089 "{\n"
1090 "       vec3 adir = abs(dir);\n"
1091 "       return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1092 "}\n"
1093 "#endif\n"
1094 "\n"
1095 "# ifdef USESHADOWMAPRECT\n"
1096 "float ShadowMapCompare(vec3 dir)\n"
1097 "{\n"
1098 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1099 "       float f;\n"
1100 "#  ifdef USESHADOWSAMPLER\n"
1101 "\n"
1102 "#    ifdef USESHADOWMAPPCF\n"
1103 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1104 "       f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1105 "#    else\n"
1106 "       f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1107 "#    endif\n"
1108 "\n"
1109 "#  else\n"
1110 "\n"
1111 "#    ifdef USESHADOWMAPPCF\n"
1112 "#      if USESHADOWMAPPCF > 1\n"
1113 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1114 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1115 "       vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1116 "       vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
1117 "       vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
1118 "       vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
1119 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1120 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1121 "#      else\n"
1122 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1123 "       vec2 offset = fract(shadowmaptc.xy);\n"
1124 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1125 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1126 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1127 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1128 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1129 "#      endif\n"
1130 "#    else\n"
1131 "       f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1132 "#    endif\n"
1133 "\n"
1134 "#  endif\n"
1135 "#  ifdef USESHADOWMAPORTHO\n"
1136 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1137 "#  else\n"
1138 "       return f;\n"
1139 "#  endif\n"
1140 "}\n"
1141 "# endif\n"
1142 "\n"
1143 "# ifdef USESHADOWMAP2D\n"
1144 "float ShadowMapCompare(vec3 dir)\n"
1145 "{\n"
1146 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1147 "       float f;\n"
1148 "\n"
1149 "#  ifdef USESHADOWSAMPLER\n"
1150 "#    ifdef USESHADOWMAPPCF\n"
1151 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1152 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1153 "       f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1154 "#    else\n"
1155 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1156 "#    endif\n"
1157 "#  else\n"
1158 "#    ifdef USESHADOWMAPPCF\n"
1159 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1160 "#      ifdef GL_ARB_texture_gather\n"
1161 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1162 "#      else\n"
1163 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1164 "#      endif\n"
1165 "       vec2 center = shadowmaptc.xy - 1.5, offset = fract(center);\n"
1166 "       center = (center - offset)*ShadowMap_TextureScale;\n"
1167 "       vec4 group1 = step(shadowmaptc.z, texval(0.0, 0.0));\n"
1168 "       vec4 group2 = step(shadowmaptc.z, texval(2.0, 0.0));\n"
1169 "       vec4 group3 = step(shadowmaptc.z, texval(0.0, 2.0));\n"
1170 "       vec4 group4 = step(shadowmaptc.z, texval(2.0, 2.0));\n"
1171 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1172 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1173 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1174 "#     else\n"
1175 "#      ifdef GL_EXT_gpu_shader4\n"
1176 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1177 "#      else\n"
1178 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1179 "#      endif\n"
1180 "#      if USESHADOWMAPPCF > 1\n"
1181 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1182 "       center *= ShadowMap_TextureScale;\n"
1183 "       vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1184 "       vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
1185 "       vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
1186 "       vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
1187 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1188 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1189 "#      else\n"
1190 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1191 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1192 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1193 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1194 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1195 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1196 "#      endif\n"
1197 "#     endif\n"
1198 "#    else\n"
1199 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1200 "#    endif\n"
1201 "#  endif\n"
1202 "#  ifdef USESHADOWMAPORTHO\n"
1203 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1204 "#  else\n"
1205 "       return f;\n"
1206 "#  endif\n"
1207 "}\n"
1208 "# endif\n"
1209 "\n"
1210 "# ifdef USESHADOWMAPCUBE\n"
1211 "float ShadowMapCompare(vec3 dir)\n"
1212 "{\n"
1213 "       // apply depth texture cubemap as light filter\n"
1214 "       vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1215 "       float f;\n"
1216 "#  ifdef USESHADOWSAMPLER\n"
1217 "       f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1218 "#  else\n"
1219 "       f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1220 "#  endif\n"
1221 "       return f;\n"
1222 "}\n"
1223 "# endif\n"
1224 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1225 "#endif // FRAGMENT_SHADER\n"
1226 "\n"
1227 "\n"
1228 "\n"
1229 "\n"
1230 "#ifdef MODE_DEFERREDGEOMETRY\n"
1231 "#ifdef VERTEX_SHADER\n"
1232 "uniform mat4 TexMatrix;\n"
1233 "#ifdef USEVERTEXTEXTUREBLEND\n"
1234 "uniform mat4 BackgroundTexMatrix;\n"
1235 "#endif\n"
1236 "uniform mat4 ModelViewMatrix;\n"
1237 "void main(void)\n"
1238 "{\n"
1239 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1240 "#ifdef USEVERTEXTEXTUREBLEND\n"
1241 "       gl_FrontColor = gl_Color;\n"
1242 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1243 "#endif\n"
1244 "\n"
1245 "       // transform unnormalized eye direction into tangent space\n"
1246 "#ifdef USEOFFSETMAPPING\n"
1247 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1248 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1249 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1250 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1251 "#endif\n"
1252 "\n"
1253 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1254 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1255 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1256 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1257 "}\n"
1258 "#endif // VERTEX_SHADER\n"
1259 "\n"
1260 "#ifdef FRAGMENT_SHADER\n"
1261 "void main(void)\n"
1262 "{\n"
1263 "#ifdef USEOFFSETMAPPING\n"
1264 "       // apply offsetmapping\n"
1265 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1266 "#define TexCoord TexCoordOffset\n"
1267 "#endif\n"
1268 "\n"
1269 "#ifdef USEALPHAKILL\n"
1270 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1271 "               discard;\n"
1272 "#endif\n"
1273 "\n"
1274 "#ifdef USEVERTEXTEXTUREBLEND\n"
1275 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1276 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1277 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1278 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1279 "#endif\n"
1280 "\n"
1281 "#ifdef USEVERTEXTEXTUREBLEND\n"
1282 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1283 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1284 "#else\n"
1285 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1286 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1287 "#endif\n"
1288 "\n"
1289 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1290 "}\n"
1291 "#endif // FRAGMENT_SHADER\n"
1292 "#else // !MODE_DEFERREDGEOMETRY\n"
1293 "\n"
1294 "\n"
1295 "\n"
1296 "\n"
1297 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1298 "#ifdef VERTEX_SHADER\n"
1299 "uniform mat4 ModelViewMatrix;\n"
1300 "void main(void)\n"
1301 "{\n"
1302 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1303 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1304 "}\n"
1305 "#endif // VERTEX_SHADER\n"
1306 "\n"
1307 "#ifdef FRAGMENT_SHADER\n"
1308 "uniform mat4 ViewToLight;\n"
1309 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1310 "uniform vec2 ScreenToDepth;\n"
1311 "uniform myhalf3 DeferredColor_Ambient;\n"
1312 "uniform myhalf3 DeferredColor_Diffuse;\n"
1313 "#ifdef USESPECULAR\n"
1314 "uniform myhalf3 DeferredColor_Specular;\n"
1315 "uniform myhalf SpecularPower;\n"
1316 "#endif\n"
1317 "uniform myhalf2 PixelToScreenTexCoord;\n"
1318 "void main(void)\n"
1319 "{\n"
1320 "       // calculate viewspace pixel position\n"
1321 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1322 "       vec3 position;\n"
1323 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1324 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1325 "       // decode viewspace pixel normal\n"
1326 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1327 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1328 "       // surfacenormal = pixel normal in viewspace\n"
1329 "       // LightVector = pixel to light in viewspace\n"
1330 "       // CubeVector = position in lightspace\n"
1331 "       // eyevector = pixel to view in viewspace\n"
1332 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1333 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1334 "#ifdef USEDIFFUSE\n"
1335 "       // calculate diffuse shading\n"
1336 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1337 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1338 "#endif\n"
1339 "#ifdef USESPECULAR\n"
1340 "       // calculate directional shading\n"
1341 "       vec3 eyevector = position * -1.0;\n"
1342 "#  ifdef USEEXACTSPECULARMATH\n"
1343 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1344 "#  else\n"
1345 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1346 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1347 "#  endif\n"
1348 "#endif\n"
1349 "\n"
1350 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1351 "       fade *= ShadowMapCompare(CubeVector);\n"
1352 "#endif\n"
1353 "\n"
1354 "#ifdef USEDIFFUSE\n"
1355 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1356 "#else\n"
1357 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1358 "#endif\n"
1359 "#ifdef USESPECULAR\n"
1360 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1361 "#else\n"
1362 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1363 "#endif\n"
1364 "\n"
1365 "# ifdef USECUBEFILTER\n"
1366 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1367 "       gl_FragData[0].rgb *= cubecolor;\n"
1368 "       gl_FragData[1].rgb *= cubecolor;\n"
1369 "# endif\n"
1370 "}\n"
1371 "#endif // FRAGMENT_SHADER\n"
1372 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1373 "\n"
1374 "\n"
1375 "\n"
1376 "\n"
1377 "#ifdef VERTEX_SHADER\n"
1378 "uniform mat4 TexMatrix;\n"
1379 "#ifdef USEVERTEXTEXTUREBLEND\n"
1380 "uniform mat4 BackgroundTexMatrix;\n"
1381 "#endif\n"
1382 "#ifdef MODE_LIGHTSOURCE\n"
1383 "uniform mat4 ModelToLight;\n"
1384 "#endif\n"
1385 "#ifdef USESHADOWMAPORTHO\n"
1386 "uniform mat4 ShadowMapMatrix;\n"
1387 "#endif\n"
1388 "void main(void)\n"
1389 "{\n"
1390 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1391 "       gl_FrontColor = gl_Color;\n"
1392 "#endif\n"
1393 "       // copy the surface texcoord\n"
1394 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1395 "#ifdef USEVERTEXTEXTUREBLEND\n"
1396 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1397 "#endif\n"
1398 "#ifdef USELIGHTMAP\n"
1399 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1400 "#endif\n"
1401 "\n"
1402 "#ifdef MODE_LIGHTSOURCE\n"
1403 "       // transform vertex position into light attenuation/cubemap space\n"
1404 "       // (-1 to +1 across the light box)\n"
1405 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1406 "\n"
1407 "# ifdef USEDIFFUSE\n"
1408 "       // transform unnormalized light direction into tangent space\n"
1409 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1410 "       //  normalize it per pixel)\n"
1411 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1412 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1413 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1414 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1415 "# endif\n"
1416 "#endif\n"
1417 "\n"
1418 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1419 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1420 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1421 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1422 "#endif\n"
1423 "\n"
1424 "       // transform unnormalized eye direction into tangent space\n"
1425 "#ifdef USEEYEVECTOR\n"
1426 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1427 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1428 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1429 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1430 "#endif\n"
1431 "\n"
1432 "#ifdef USEFOG\n"
1433 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1434 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1435 "#endif\n"
1436 "\n"
1437 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1438 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1439 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1440 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1441 "#endif\n"
1442 "\n"
1443 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1444 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1445 "\n"
1446 "#ifdef USESHADOWMAPORTHO\n"
1447 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1448 "#endif\n"
1449 "\n"
1450 "#ifdef USEREFLECTION\n"
1451 "       ModelViewProjectionPosition = gl_Position;\n"
1452 "#endif\n"
1453 "}\n"
1454 "#endif // VERTEX_SHADER\n"
1455 "\n"
1456 "\n"
1457 "\n"
1458 "\n"
1459 "#ifdef FRAGMENT_SHADER\n"
1460 "#ifdef USEDEFERREDLIGHTMAP\n"
1461 "uniform myhalf2 PixelToScreenTexCoord;\n"
1462 "uniform myhalf3 DeferredMod_Diffuse;\n"
1463 "uniform myhalf3 DeferredMod_Specular;\n"
1464 "#endif\n"
1465 "uniform myhalf3 Color_Ambient;\n"
1466 "uniform myhalf3 Color_Diffuse;\n"
1467 "uniform myhalf3 Color_Specular;\n"
1468 "uniform myhalf SpecularPower;\n"
1469 "#ifdef USEGLOW\n"
1470 "uniform myhalf3 Color_Glow;\n"
1471 "#endif\n"
1472 "uniform myhalf Alpha;\n"
1473 "#ifdef USEREFLECTION\n"
1474 "uniform vec4 DistortScaleRefractReflect;\n"
1475 "uniform vec4 ScreenScaleRefractReflect;\n"
1476 "uniform vec4 ScreenCenterRefractReflect;\n"
1477 "uniform myhalf4 ReflectColor;\n"
1478 "#endif\n"
1479 "#ifdef USEREFLECTCUBE\n"
1480 "uniform mat4 ModelToReflectCube;\n"
1481 "uniform sampler2D Texture_ReflectMask;\n"
1482 "uniform samplerCube Texture_ReflectCube;\n"
1483 "#endif\n"
1484 "#ifdef MODE_LIGHTDIRECTION\n"
1485 "uniform myhalf3 LightColor;\n"
1486 "#endif\n"
1487 "#ifdef MODE_LIGHTSOURCE\n"
1488 "uniform myhalf3 LightColor;\n"
1489 "#endif\n"
1490 "void main(void)\n"
1491 "{\n"
1492 "#ifdef USEOFFSETMAPPING\n"
1493 "       // apply offsetmapping\n"
1494 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1495 "#define TexCoord TexCoordOffset\n"
1496 "#endif\n"
1497 "\n"
1498 "       // combine the diffuse textures (base, pants, shirt)\n"
1499 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1500 "#ifdef USEALPHAKILL\n"
1501 "       if (color.a < 0.5)\n"
1502 "               discard;\n"
1503 "#endif\n"
1504 "       color.a *= Alpha;\n"
1505 "#ifdef USECOLORMAPPING\n"
1506 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1507 "#endif\n"
1508 "#ifdef USEVERTEXTEXTUREBLEND\n"
1509 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1510 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1511 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1512 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1513 "       color.a = 1.0;\n"
1514 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1515 "#endif\n"
1516 "\n"
1517 "       // get the surface normal\n"
1518 "#ifdef USEVERTEXTEXTUREBLEND\n"
1519 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1520 "#else\n"
1521 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1522 "#endif\n"
1523 "\n"
1524 "       // get the material colors\n"
1525 "       myhalf3 diffusetex = color.rgb;\n"
1526 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1527 "# ifdef USEVERTEXTEXTUREBLEND\n"
1528 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1529 "# else\n"
1530 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1531 "# endif\n"
1532 "#endif\n"
1533 "\n"
1534 "#ifdef USEREFLECTCUBE\n"
1535 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1536 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1537 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1538 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1539 "#endif\n"
1540 "\n"
1541 "\n"
1542 "\n"
1543 "\n"
1544 "#ifdef MODE_LIGHTSOURCE\n"
1545 "       // light source\n"
1546 "#ifdef USEDIFFUSE\n"
1547 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1548 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1549 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1550 "#ifdef USESPECULAR\n"
1551 "#ifdef USEEXACTSPECULARMATH\n"
1552 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1553 "#else\n"
1554 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1555 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1556 "#endif\n"
1557 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1558 "#endif\n"
1559 "#else\n"
1560 "       color.rgb = diffusetex * Color_Ambient;\n"
1561 "#endif\n"
1562 "       color.rgb *= LightColor;\n"
1563 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1564 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1565 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1566 "#endif\n"
1567 "# ifdef USECUBEFILTER\n"
1568 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1569 "# endif\n"
1570 "#endif // MODE_LIGHTSOURCE\n"
1571 "\n"
1572 "\n"
1573 "\n"
1574 "\n"
1575 "#ifdef MODE_LIGHTDIRECTION\n"
1576 "#define SHADING\n"
1577 "#ifdef USEDIFFUSE\n"
1578 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1579 "#endif\n"
1580 "#define lightcolor LightColor\n"
1581 "#endif // MODE_LIGHTDIRECTION\n"
1582 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1583 "#define SHADING\n"
1584 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1585 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1586 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1587 "       // convert modelspace light vector to tangentspace\n"
1588 "       myhalf3 lightnormal;\n"
1589 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1590 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1591 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1592 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1593 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1594 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1595 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1596 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1597 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1598 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1599 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1600 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1601 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1602 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1603 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1604 "#define SHADING\n"
1605 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1606 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1607 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1608 "#endif\n"
1609 "\n"
1610 "\n"
1611 "\n"
1612 "\n"
1613 "#ifdef MODE_LIGHTMAP\n"
1614 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1615 "#endif // MODE_LIGHTMAP\n"
1616 "#ifdef MODE_VERTEXCOLOR\n"
1617 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1618 "#endif // MODE_VERTEXCOLOR\n"
1619 "#ifdef MODE_FLATCOLOR\n"
1620 "       color.rgb = diffusetex * Color_Ambient;\n"
1621 "#endif // MODE_FLATCOLOR\n"
1622 "\n"
1623 "\n"
1624 "\n"
1625 "\n"
1626 "#ifdef SHADING\n"
1627 "# ifdef USEDIFFUSE\n"
1628 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1629 "#  ifdef USESPECULAR\n"
1630 "#   ifdef USEEXACTSPECULARMATH\n"
1631 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1632 "#   else\n"
1633 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1634 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1635 "#   endif\n"
1636 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1637 "#  else\n"
1638 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1639 "#  endif\n"
1640 "# else\n"
1641 "       color.rgb = diffusetex * Color_Ambient;\n"
1642 "# endif\n"
1643 "#endif\n"
1644 "\n"
1645 "#ifdef USESHADOWMAPORTHO\n"
1646 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1647 "#endif\n"
1648 "\n"
1649 "#ifdef USEDEFERREDLIGHTMAP\n"
1650 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1651 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1652 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1653 "#endif\n"
1654 "\n"
1655 "#ifdef USEGLOW\n"
1656 "#ifdef USEVERTEXTEXTUREBLEND\n"
1657 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1658 "#else\n"
1659 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1660 "#endif\n"
1661 "#endif\n"
1662 "\n"
1663 "#ifdef USEFOG\n"
1664 "#ifdef MODE_LIGHTSOURCE\n"
1665 "       color.rgb *= myhalf(FogVertex());\n"
1666 "#else\n"
1667 "       color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1668 "#endif\n"
1669 "#endif\n"
1670 "\n"
1671 "       // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
1672 "#ifdef USEREFLECTION\n"
1673 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1674 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1675 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1676 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1677 "       // FIXME temporary hack to detect the case that the reflection\n"
1678 "       // gets blackened at edges due to leaving the area that contains actual\n"
1679 "       // content.\n"
1680 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1681 "       // 'appening.\n"
1682 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1683 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1684 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1685 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1686 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1687 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1688 "#endif\n"
1689 "\n"
1690 "       gl_FragColor = vec4(color);\n"
1691 "}\n"
1692 "#endif // FRAGMENT_SHADER\n"
1693 "\n"
1694 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1695 "#endif // !MODE_DEFERREDGEOMETRY\n"
1696 "#endif // !MODE_WATER\n"
1697 "#endif // !MODE_REFRACTION\n"
1698 "#endif // !MODE_BLOOMBLUR\n"
1699 "#endif // !MODE_GENERIC\n"
1700 "#endif // !MODE_POSTPROCESS\n"
1701 "#endif // !MODE_SHOWDEPTH\n"
1702 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1703 ;
1704
1705 /*
1706 =========================================================================================================================================================
1707
1708
1709
1710 =========================================================================================================================================================
1711
1712
1713
1714 =========================================================================================================================================================
1715
1716
1717
1718 =========================================================================================================================================================
1719
1720
1721
1722 =========================================================================================================================================================
1723
1724
1725
1726 =========================================================================================================================================================
1727
1728
1729
1730 =========================================================================================================================================================
1731 */
1732
1733 const char *builtincgshaderstring =
1734 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1735 "// written by Forest 'LordHavoc' Hale\n"
1736 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1737 "\n"
1738 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
1739 "# define USEFOG\n"
1740 "#endif\n"
1741 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1742 "#define USELIGHTMAP\n"
1743 "#endif\n"
1744 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
1745 "#define USEEYEVECTOR\n"
1746 "#endif\n"
1747 "\n"
1748 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1749 "#ifdef VERTEX_SHADER\n"
1750 "void main\n"
1751 "(\n"
1752 "float4 gl_Vertex : POSITION,\n"
1753 "uniform float4x4 ModelViewProjectionMatrix,\n"
1754 "out float4 gl_Position : POSITION\n"
1755 ")\n"
1756 "{\n"
1757 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1758 "}\n"
1759 "#endif\n"
1760 "#else // !MODE_DEPTH_ORSHADOW\n"
1761 "\n"
1762 "\n"
1763 "\n"
1764 "\n"
1765 "#ifdef MODE_SHOWDEPTH\n"
1766 "#ifdef VERTEX_SHADER\n"
1767 "void main\n"
1768 "(\n"
1769 "float4 gl_Vertex : POSITION,\n"
1770 "uniform float4x4 ModelViewProjectionMatrix,\n"
1771 "out float4 gl_Position : POSITION,\n"
1772 "out float4 gl_FrontColor : COLOR0\n"
1773 ")\n"
1774 "{\n"
1775 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1776 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1777 "}\n"
1778 "#endif\n"
1779 "\n"
1780 "#ifdef FRAGMENT_SHADER\n"
1781 "void main\n"
1782 "(\n"
1783 "float4 gl_FrontColor : COLOR0,\n"
1784 "out float4 gl_FragColor : COLOR\n"
1785 ")\n"
1786 "{\n"
1787 "       gl_FragColor = gl_FrontColor;\n"
1788 "}\n"
1789 "#endif\n"
1790 "#else // !MODE_SHOWDEPTH\n"
1791 "\n"
1792 "\n"
1793 "\n"
1794 "\n"
1795 "#ifdef MODE_POSTPROCESS\n"
1796 "\n"
1797 "#ifdef VERTEX_SHADER\n"
1798 "void main\n"
1799 "(\n"
1800 "float4 gl_Vertex : POSITION,\n"
1801 "uniform float4x4 ModelViewProjectionMatrix,\n"
1802 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1803 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1804 "out float4 gl_Position : POSITION,\n"
1805 "out float2 TexCoord1 : TEXCOORD0,\n"
1806 "out float2 TexCoord2 : TEXCOORD1\n"
1807 ")\n"
1808 "{\n"
1809 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1810 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1811 "#ifdef USEBLOOM\n"
1812 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1813 "#endif\n"
1814 "}\n"
1815 "#endif\n"
1816 "\n"
1817 "#ifdef FRAGMENT_SHADER\n"
1818 "void main\n"
1819 "(\n"
1820 "float2 TexCoord1 : TEXCOORD0,\n"
1821 "float2 TexCoord2 : TEXCOORD1,\n"
1822 "uniform sampler2D Texture_First,\n"
1823 "#ifdef USEBLOOM\n"
1824 "uniform sampler2D Texture_Second,\n"
1825 "#endif\n"
1826 "#ifdef USEGAMMARAMPS\n"
1827 "uniform sampler2D Texture_GammaRamps,\n"
1828 "#endif\n"
1829 "#ifdef USESATURATION\n"
1830 "uniform float Saturation,\n"
1831 "#endif\n"
1832 "#ifdef USEVIEWTINT\n"
1833 "uniform float4 ViewTintColor,\n"
1834 "#endif\n"
1835 "uniform float4 UserVec1,\n"
1836 "uniform float4 UserVec2,\n"
1837 "uniform float4 UserVec3,\n"
1838 "uniform float4 UserVec4,\n"
1839 "uniform float ClientTime,\n"
1840 "uniform float2 PixelSize,\n"
1841 "out float4 gl_FragColor : COLOR\n"
1842 ")\n"
1843 "{\n"
1844 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1845 "#ifdef USEBLOOM\n"
1846 "       gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
1847 "#endif\n"
1848 "#ifdef USEVIEWTINT\n"
1849 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1850 "#endif\n"
1851 "\n"
1852 "#ifdef USEPOSTPROCESSING\n"
1853 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1854 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
1855 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1856 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1857 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1858 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
1859 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
1860 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
1861 "#endif\n"
1862 "\n"
1863 "#ifdef USESATURATION\n"
1864 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
1865 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
1866 "       //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
1867 "       gl_FragColor.rgb = lerp(float3(y), gl_FragColor.rgb, Saturation);\n"
1868 "#endif\n"
1869 "\n"
1870 "#ifdef USEGAMMARAMPS\n"
1871 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
1872 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
1873 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
1874 "#endif\n"
1875 "}\n"
1876 "#endif\n"
1877 "#else // !MODE_POSTPROCESS\n"
1878 "\n"
1879 "\n"
1880 "\n"
1881 "\n"
1882 "#ifdef MODE_GENERIC\n"
1883 "#ifdef VERTEX_SHADER\n"
1884 "void main\n"
1885 "(\n"
1886 "float4 gl_Vertex : POSITION,\n"
1887 "uniform float4x4 ModelViewProjectionMatrix,\n"
1888 "float4 gl_Color : COLOR0,\n"
1889 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1890 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1891 "out float4 gl_Position : POSITION,\n"
1892 "out float4 gl_FrontColor : COLOR,\n"
1893 "out float2 TexCoord1 : TEXCOORD0,\n"
1894 "out float2 TexCoord2 : TEXCOORD1\n"
1895 ")\n"
1896 "{\n"
1897 "       gl_FrontColor = gl_Color;\n"
1898 "#ifdef USEDIFFUSE\n"
1899 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1900 "#endif\n"
1901 "#ifdef USESPECULAR\n"
1902 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1903 "#endif\n"
1904 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1905 "}\n"
1906 "#endif\n"
1907 "\n"
1908 "#ifdef FRAGMENT_SHADER\n"
1909 "\n"
1910 "void main\n"
1911 "(\n"
1912 "float4 gl_FrontColor : COLOR,\n"
1913 "float2 TexCoord1 : TEXCOORD0,\n"
1914 "float2 TexCoord2 : TEXCOORD1,\n"
1915 "#ifdef USEDIFFUSE\n"
1916 "uniform sampler2D Texture_First,\n"
1917 "#endif\n"
1918 "#ifdef USESPECULAR\n"
1919 "uniform sampler2D Texture_Second,\n"
1920 "#endif\n"
1921 "out float4 gl_FragColor : COLOR\n"
1922 ")\n"
1923 "{\n"
1924 "       gl_FragColor = gl_FrontColor;\n"
1925 "#ifdef USEDIFFUSE\n"
1926 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
1927 "#endif\n"
1928 "\n"
1929 "#ifdef USESPECULAR\n"
1930 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
1931 "# ifdef USECOLORMAPPING\n"
1932 "       gl_FragColor *= tex2;\n"
1933 "# endif\n"
1934 "# ifdef USEGLOW\n"
1935 "       gl_FragColor += tex2;\n"
1936 "# endif\n"
1937 "# ifdef USEVERTEXTEXTUREBLEND\n"
1938 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
1939 "# endif\n"
1940 "#endif\n"
1941 "}\n"
1942 "#endif\n"
1943 "#else // !MODE_GENERIC\n"
1944 "\n"
1945 "\n"
1946 "\n"
1947 "\n"
1948 "#ifdef MODE_BLOOMBLUR\n"
1949 "#ifdef VERTEX_SHADER\n"
1950 "void main\n"
1951 "(\n"
1952 "float4 gl_Vertex : POSITION,\n"
1953 "uniform float4x4 ModelViewProjectionMatrix,\n"
1954 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1955 "out float4 gl_Position : POSITION,\n"
1956 "out float2 TexCoord : TEXCOORD0\n"
1957 ")\n"
1958 "{\n"
1959 "       TexCoord = gl_MultiTexCoord0.xy;\n"
1960 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1961 "}\n"
1962 "#endif\n"
1963 "\n"
1964 "#ifdef FRAGMENT_SHADER\n"
1965 "\n"
1966 "void main\n"
1967 "(\n"
1968 "float2 TexCoord : TEXCOORD0,\n"
1969 "uniform sampler2D Texture_First,\n"
1970 "uniform float4 BloomBlur_Parameters,\n"
1971 "out float4 gl_FragColor : COLOR\n"
1972 ")\n"
1973 "{\n"
1974 "       int i;\n"
1975 "       float2 tc = TexCoord;\n"
1976 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
1977 "       tc += BloomBlur_Parameters.xy;\n"
1978 "       for (i = 1;i < SAMPLES;i++)\n"
1979 "       {\n"
1980 "               color += tex2D(Texture_First, tc).rgb;\n"
1981 "               tc += BloomBlur_Parameters.xy;\n"
1982 "       }\n"
1983 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
1984 "}\n"
1985 "#endif\n"
1986 "#else // !MODE_BLOOMBLUR\n"
1987 "#ifdef MODE_REFRACTION\n"
1988 "#ifdef VERTEX_SHADER\n"
1989 "void main\n"
1990 "(\n"
1991 "float4 gl_Vertex : POSITION,\n"
1992 "uniform float4x4 ModelViewProjectionMatrix,\n"
1993 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1994 "uniform float4x4 TexMatrix,\n"
1995 "uniform float3 EyePosition,\n"
1996 "out float4 gl_Position : POSITION,\n"
1997 "out float2 TexCoord : TEXCOORD0,\n"
1998 "out float3 EyeVector : TEXCOORD1,\n"
1999 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2000 ")\n"
2001 "{\n"
2002 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2003 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2004 "       ModelViewProjectionPosition = gl_Position;\n"
2005 "}\n"
2006 "#endif\n"
2007 "\n"
2008 "#ifdef FRAGMENT_SHADER\n"
2009 "void main\n"
2010 "(\n"
2011 "float2 TexCoord : TEXCOORD0,\n"
2012 "float3 EyeVector : TEXCOORD1,\n"
2013 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2014 "uniform sampler2D Texture_Normal,\n"
2015 "uniform sampler2D Texture_Refraction,\n"
2016 "uniform sampler2D Texture_Reflection,\n"
2017 "uniform float4 DistortScaleRefractReflect,\n"
2018 "uniform float4 ScreenScaleRefractReflect,\n"
2019 "uniform float4 ScreenCenterRefractReflect,\n"
2020 "uniform float4 RefractColor,\n"
2021 "out float4 gl_FragColor : COLOR\n"
2022 ")\n"
2023 "{\n"
2024 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2025 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2026 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2027 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
2028 "       // FIXME temporary hack to detect the case that the reflection\n"
2029 "       // gets blackened at edges due to leaving the area that contains actual\n"
2030 "       // content.\n"
2031 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2032 "       // 'appening.\n"
2033 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2034 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2035 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2036 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2037 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2038 "       gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2039 "}\n"
2040 "#endif\n"
2041 "#else // !MODE_REFRACTION\n"
2042 "\n"
2043 "\n"
2044 "\n"
2045 "\n"
2046 "#ifdef MODE_WATER\n"
2047 "#ifdef VERTEX_SHADER\n"
2048 "\n"
2049 "void main\n"
2050 "(\n"
2051 "float4 gl_Vertex : POSITION,\n"
2052 "uniform float4x4 ModelViewProjectionMatrix,\n"
2053 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2054 "uniform float4x4 TexMatrix,\n"
2055 "uniform float3 EyePosition,\n"
2056 "out float4 gl_Position : POSITION,\n"
2057 "out float2 TexCoord : TEXCOORD0,\n"
2058 "out float3 EyeVector : TEXCOORD1,\n"
2059 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2060 ")\n"
2061 "{\n"
2062 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2063 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2064 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2065 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2066 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2067 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2068 "       ModelViewProjectionPosition = gl_Position;\n"
2069 "}\n"
2070 "#endif\n"
2071 "\n"
2072 "#ifdef FRAGMENT_SHADER\n"
2073 "void main\n"
2074 "(\n"
2075 "float2 TexCoord : TEXCOORD0,\n"
2076 "float3 EyeVector : TEXCOORD1,\n"
2077 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2078 "uniform sampler2D Texture_Normal,\n"
2079 "uniform sampler2D Texture_Refraction,\n"
2080 "uniform sampler2D Texture_Reflection,\n"
2081 "uniform float4 DistortScaleRefractReflect,\n"
2082 "uniform float4 ScreenScaleRefractReflect,\n"
2083 "uniform float4 ScreenCenterRefractReflect,\n"
2084 "uniform float4 RefractColor,\n"
2085 "uniform float4 ReflectColor,\n"
2086 "uniform float ReflectFactor,\n"
2087 "uniform float ReflectOffset,\n"
2088 "out float4 gl_FragColor : COLOR\n"
2089 ")\n"
2090 "{\n"
2091 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2092 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2093 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2094 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xyxy * DistortScaleRefractReflect;\n"
2095 "       // FIXME temporary hack to detect the case that the reflection\n"
2096 "       // gets blackened at edges due to leaving the area that contains actual\n"
2097 "       // content.\n"
2098 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2099 "       // 'appening.\n"
2100 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2101 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2102 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2103 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2104 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2105 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2106 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2107 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2108 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2109 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2110 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2111 "       gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2112 "}\n"
2113 "#endif\n"
2114 "#else // !MODE_WATER\n"
2115 "\n"
2116 "\n"
2117 "\n"
2118 "\n"
2119 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
2120 "\n"
2121 "// fragment shader specific:\n"
2122 "#ifdef FRAGMENT_SHADER\n"
2123 "\n"
2124 "#ifdef USEFOG\n"
2125 "float FogVertex(float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask)\n"
2126 "{\n"
2127 "       float fogfrac;\n"
2128 "#ifdef USEFOGOUTSIDE\n"
2129 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2130 "#else\n"
2131 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2132 "#endif\n"
2133 "       return float(tex2D(Texture_FogMask, half2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
2134 "}\n"
2135 "#endif\n"
2136 "\n"
2137 "#ifdef USEOFFSETMAPPING\n"
2138 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler2D Texture_Normal)\n"
2139 "{\n"
2140 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2141 "       // 14 sample relief mapping: linear search and then binary search\n"
2142 "       // this basically steps forward a small amount repeatedly until it finds\n"
2143 "       // itself inside solid, then jitters forward and back using decreasing\n"
2144 "       // amounts to find the impact\n"
2145 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2146 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2147 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2148 "       float3 RT = float3(TexCoord, 1);\n"
2149 "       OffsetVector *= 0.1;\n"
2150 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2151 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2152 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2153 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2154 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2155 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2156 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2157 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2158 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2159 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2160 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2161 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2162 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2163 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2164 "       return RT.xy;\n"
2165 "#else\n"
2166 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2167 "       // this basically moves forward the full distance, and then backs up based\n"
2168 "       // on height of samples\n"
2169 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2170 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2171 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2172 "       TexCoord += OffsetVector;\n"
2173 "       OffsetVector *= 0.333;\n"
2174 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2175 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2176 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2177 "       return TexCoord;\n"
2178 "#endif\n"
2179 "}\n"
2180 "#endif // USEOFFSETMAPPING\n"
2181 "\n"
2182 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2183 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2184 "# ifdef USESHADOWMAPORTHO\n"
2185 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2186 "# else\n"
2187 "#  ifdef USESHADOWMAPVSDCT\n"
2188 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2189 "{\n"
2190 "       float3 adir = abs(dir);\n"
2191 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2192 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2193 "       return float3(lerp(dir.xy, proj.xy, dir.zz) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2194 "}\n"
2195 "#  else\n"
2196 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2197 "{\n"
2198 "       float3 adir = abs(dir);\n"
2199 "       float ma = adir.z;\n"
2200 "       float4 proj = float4(dir, 2.5);\n"
2201 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2202 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2203 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2204 "       return float3(proj.xy * aparams.x + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2205 "}\n"
2206 "#  endif\n"
2207 "# endif\n"
2208 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPORTHO)\n"
2209 "\n"
2210 "#ifdef USESHADOWMAPCUBE\n"
2211 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2212 "{\n"
2213 "    float3 adir = abs(dir);\n"
2214 "    return float4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
2215 "}\n"
2216 "#endif\n"
2217 "\n"
2218 "# ifdef USESHADOWMAPRECT\n"
2219 "#ifdef USESHADOWMAPVSDCT\n"
2220 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2221 "#else\n"
2222 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2223 "#endif\n"
2224 "{\n"
2225 "#ifdef USESHADOWMAPVSDCT\n"
2226 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2227 "#else\n"
2228 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2229 "#endif\n"
2230 "       float f;\n"
2231 "#  ifdef USESHADOWSAMPLER\n"
2232 "\n"
2233 "#    ifdef USESHADOWMAPPCF\n"
2234 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2235 "    f = dot(float4(0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2236 "#    else\n"
2237 "    f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2238 "#    endif\n"
2239 "\n"
2240 "#  else\n"
2241 "\n"
2242 "#    ifdef USESHADOWMAPPCF\n"
2243 "#      if USESHADOWMAPPCF > 1\n"
2244 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2245 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2246 "    float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
2247 "    float4 row2 = step(shadowmaptc.z, float4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
2248 "    float4 row3 = step(shadowmaptc.z, float4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
2249 "    float4 row4 = step(shadowmaptc.z, float4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
2250 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2251 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2252 "#      else\n"
2253 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2254 "    float2 offset = frac(shadowmaptc.xy);\n"
2255 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2256 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2257 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2258 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2259 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2260 "#      endif\n"
2261 "#    else\n"
2262 "    f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2263 "#    endif\n"
2264 "\n"
2265 "#  endif\n"
2266 "#  ifdef USESHADOWMAPORTHO\n"
2267 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2268 "#  else\n"
2269 "       return f;\n"
2270 "#  endif\n"
2271 "}\n"
2272 "# endif\n"
2273 "\n"
2274 "# ifdef USESHADOWMAP2D\n"
2275 "#ifdef USESHADOWMAPVSDCT\n"
2276 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2277 "#else\n"
2278 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2279 "#endif\n"
2280 "{\n"
2281 "#ifdef USESHADOWMAPVSDCT\n"
2282 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2283 "#else\n"
2284 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2285 "#endif\n"
2286 "    float f;\n"
2287 "\n"
2288 "#  ifdef USESHADOWSAMPLER\n"
2289 "#    ifdef USESHADOWMAPPCF\n"
2290 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, float3(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
2291 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2292 "    f = dot(float4(0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2293 "#    else\n"
2294 "    f = shadow2D(Texture_ShadowMap2D, float3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
2295 "#    endif\n"
2296 "#  else\n"
2297 "#    ifdef USESHADOWMAPPCF\n"
2298 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2299 "#      ifdef GL_ARB_texture_gather\n"
2300 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
2301 "#      else\n"
2302 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2303 "#      endif\n"
2304 "    float2 center = shadowmaptc.xy - 1.5, offset = fract(center);\n"
2305 "    center = (center - offset)*ShadowMap_TextureScale;\n"
2306 "    float4 group1 = step(shadowmaptc.z, texval(0.0, 0.0));\n"
2307 "    float4 group2 = step(shadowmaptc.z, texval(2.0, 0.0));\n"
2308 "    float4 group3 = step(shadowmaptc.z, texval(0.0, 2.0));\n"
2309 "    float4 group4 = step(shadowmaptc.z, texval(2.0, 2.0));\n"
2310 "    float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2311 "                lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2312 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2313 "#     else\n"
2314 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)  \n"
2315 "#      if USESHADOWMAPPCF > 1\n"
2316 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2317 "    center *= ShadowMap_TextureScale;\n"
2318 "    float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
2319 "    float4 row2 = step(shadowmaptc.z, float4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
2320 "    float4 row3 = step(shadowmaptc.z, float4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
2321 "    float4 row4 = step(shadowmaptc.z, float4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
2322 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2323 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2324 "#      else\n"
2325 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2326 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2327 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2328 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2329 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2330 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2331 "#      endif\n"
2332 "#     endif\n"
2333 "#    else\n"
2334 "    f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2335 "#    endif\n"
2336 "#  endif\n"
2337 "#  ifdef USESHADOWMAPORTHO\n"
2338 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2339 "#  else\n"
2340 "       return f;\n"
2341 "#  endif\n"
2342 "}\n"
2343 "# endif\n"
2344 "\n"
2345 "# ifdef USESHADOWMAPCUBE\n"
2346 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2347 "{\n"
2348 "    // apply depth texture cubemap as light filter\n"
2349 "    float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2350 "    float f;\n"
2351 "#  ifdef USESHADOWSAMPLER\n"
2352 "    f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2353 "#  else\n"
2354 "    f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2355 "#  endif\n"
2356 "    return f;\n"
2357 "}\n"
2358 "# endif\n"
2359 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2360 "#endif // FRAGMENT_SHADER\n"
2361 "\n"
2362 "\n"
2363 "\n"
2364 "\n"
2365 "#ifdef MODE_DEFERREDGEOMETRY\n"
2366 "#ifdef VERTEX_SHADER\n"
2367 "void main\n"
2368 "(\n"
2369 "float4 gl_Vertex : POSITION,\n"
2370 "uniform float4x4 ModelViewProjectionMatrix,\n"
2371 "#ifdef USEVERTEXTEXTUREBLEND\n"
2372 "float4 gl_Color : COLOR0,\n"
2373 "#endif\n"
2374 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2375 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2376 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2377 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2378 "uniform float4x4 TexMatrix,\n"
2379 "#ifdef USEVERTEXTEXTUREBLEND\n"
2380 "uniform float4x4 BackgroundTexMatrix,\n"
2381 "#endif\n"
2382 "uniform float4x4 ModelViewMatrix,\n"
2383 "#ifdef USEOFFSETMAPPING\n"
2384 "uniform float3 EyePosition,\n"
2385 "#endif\n"
2386 "out float4 gl_Position : POSITION,\n"
2387 "out float4 gl_FrontColor : COLOR,\n"
2388 "out float4 TexCoordBoth : TEXCOORD0,\n"
2389 "#ifdef USEOFFSETMAPPING\n"
2390 "out float3 EyeVector : TEXCOORD2,\n"
2391 "#endif\n"
2392 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2393 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2394 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2395 ")\n"
2396 "{\n"
2397 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2398 "#ifdef USEVERTEXTEXTUREBLEND\n"
2399 "       gl_FrontColor = gl_Color;\n"
2400 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2401 "#endif\n"
2402 "\n"
2403 "       // transform unnormalized eye direction into tangent space\n"
2404 "#ifdef USEOFFSETMAPPING\n"
2405 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2406 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2407 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2408 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2409 "#endif\n"
2410 "\n"
2411 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2412 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2413 "       VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2414 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2415 "}\n"
2416 "#endif // VERTEX_SHADER\n"
2417 "\n"
2418 "#ifdef FRAGMENT_SHADER\n"
2419 "void main\n"
2420 "(\n"
2421 "float4 TexCoordBoth : TEXCOORD0,\n"
2422 "float3 EyeVector : TEXCOORD2,\n"
2423 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2424 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2425 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2426 "uniform sampler2D Texture_Normal,\n"
2427 "#ifdef USEALPHAKILL\n"
2428 "uniform sampler2D Texture_Color,\n"
2429 "#endif\n"
2430 "uniform sampler2D Texture_Gloss,\n"
2431 "#ifdef USEVERTEXTEXTUREBLEND\n"
2432 "uniform sampler2D Texture_SecondaryNormal,\n"
2433 "uniform sampler2D Texture_SecondaryGloss,\n"
2434 "#endif\n"
2435 "#ifdef USEOFFSETMAPPING\n"
2436 "uniform float OffsetMapping_Scale,\n"
2437 "#endif\n"
2438 "uniform half SpecularPower,\n"
2439 "out float4 gl_FragColor : COLOR\n"
2440 ")\n"
2441 "{\n"
2442 "       float2 TexCoord = TexCoordBoth.xy;\n"
2443 "#ifdef USEOFFSETMAPPING\n"
2444 "       // apply offsetmapping\n"
2445 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2446 "#define TexCoord TexCoordOffset\n"
2447 "#endif\n"
2448 "\n"
2449 "#ifdef USEALPHAKILL\n"
2450 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2451 "               discard;\n"
2452 "#endif\n"
2453 "\n"
2454 "#ifdef USEVERTEXTEXTUREBLEND\n"
2455 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2456 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2457 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2458 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2459 "#endif\n"
2460 "\n"
2461 "#ifdef USEVERTEXTEXTUREBLEND\n"
2462 "       float3 surfacenormal = lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
2463 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2464 "#else\n"
2465 "       float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
2466 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2467 "#endif\n"
2468 "\n"
2469 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), 1);\n"
2470 "}\n"
2471 "#endif // FRAGMENT_SHADER\n"
2472 "#else // !MODE_DEFERREDGEOMETRY\n"
2473 "\n"
2474 "\n"
2475 "\n"
2476 "\n"
2477 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2478 "#ifdef VERTEX_SHADER\n"
2479 "void main\n"
2480 "(\n"
2481 "float4 gl_Vertex : POSITION,\n"
2482 "uniform float4x4 ModelViewProjectionMatrix,\n"
2483 "uniform float4x4 ModelViewMatrix,\n"
2484 "out float4 gl_Position : POSITION,\n"
2485 "out float4 ModelViewPosition : TEXCOORD0\n"
2486 ")\n"
2487 "{\n"
2488 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2489 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2490 "}\n"
2491 "#endif // VERTEX_SHADER\n"
2492 "\n"
2493 "#ifdef FRAGMENT_SHADER\n"
2494 "void main\n"
2495 "(\n"
2496 "float2 Pixel : WPOS,\n"
2497 "float4 ModelViewPosition : TEXCOORD0,\n"
2498 "uniform float4x4 ViewToLight,\n"
2499 "uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2500 "uniform float3 LightPosition,\n"
2501 "uniform half2 PixelToScreenTexCoord,\n"
2502 "uniform half3 DeferredColor_Ambient,\n"
2503 "uniform half3 DeferredColor_Diffuse,\n"
2504 "#ifdef USESPECULAR\n"
2505 "uniform half3 DeferredColor_Specular,\n"
2506 "uniform half SpecularPower,\n"
2507 "#endif\n"
2508 "uniform sampler2D Texture_Attenuation,\n"
2509 "uniform sampler2D Texture_ScreenDepth,\n"
2510 "uniform sampler2D Texture_ScreenNormalMap,\n"
2511 "\n"
2512 "#ifdef USESHADOWMAPRECT\n"
2513 "# ifdef USESHADOWSAMPLER\n"
2514 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2515 "# else\n"
2516 "uniform samplerRECT Texture_ShadowMapRect,\n"
2517 "# endif\n"
2518 "#endif\n"
2519 "\n"
2520 "#ifdef USESHADOWMAP2D\n"
2521 "# ifdef USESHADOWSAMPLER\n"
2522 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2523 "# else\n"
2524 "uniform sampler2D Texture_ShadowMap2D,\n"
2525 "# endif\n"
2526 "#endif\n"
2527 "\n"
2528 "#ifdef USESHADOWMAPVSDCT\n"
2529 "uniform samplerCUBE Texture_CubeProjection,\n"
2530 "#endif\n"
2531 "\n"
2532 "#ifdef USESHADOWMAPCUBE\n"
2533 "# ifdef USESHADOWSAMPLER\n"
2534 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2535 "# else\n"
2536 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2537 "# endif\n"
2538 "#endif\n"
2539 "\n"
2540 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2541 "uniform float2 ShadowMap_TextureScale,\n"
2542 "uniform float4 ShadowMap_Parameters,\n"
2543 "#endif\n"
2544 "\n"
2545 "out float4 gl_FragData0 : COLOR0,\n"
2546 "out float4 gl_FragData1 : COLOR1\n"
2547 ")\n"
2548 "{\n"
2549 "       // calculate viewspace pixel position\n"
2550 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2551 "       ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2552 "       float3 position;\n"
2553 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2554 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2555 "       // decode viewspace pixel normal\n"
2556 "       half4 normalmap = tex2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
2557 "       half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
2558 "       // surfacenormal = pixel normal in viewspace\n"
2559 "       // LightVector = pixel to light in viewspace\n"
2560 "       // CubeVector = position in lightspace\n"
2561 "       // eyevector = pixel to view in viewspace\n"
2562 "       float3 CubeVector = float3(mul(ViewToLight, float4(position,1)));\n"
2563 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2564 "#ifdef USEDIFFUSE\n"
2565 "       // calculate diffuse shading\n"
2566 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2567 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2568 "#endif\n"
2569 "#ifdef USESPECULAR\n"
2570 "       // calculate directional shading\n"
2571 "       float3 eyevector = position * -1.0;\n"
2572 "#  ifdef USEEXACTSPECULARMATH\n"
2573 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
2574 "#  else\n"
2575 "       half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
2576 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
2577 "#  endif\n"
2578 "#endif\n"
2579 "\n"
2580 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2581 "       fade *= ShadowMapCompare(CubeVector,\n"
2582 "# if defined(USESHADOWMAP2D)\n"
2583 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2584 "# endif\n"
2585 "# if defined(USESHADOWMAPRECT)\n"
2586 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2587 "# endif\n"
2588 "# if defined(USESHADOWMAPCUBE)\n"
2589 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2590 "# endif\n"
2591 "\n"
2592 "#ifdef USESHADOWMAPVSDCT\n"
2593 ", Texture_CubeProjection\n"
2594 "#endif\n"
2595 "       );\n"
2596 "#endif\n"
2597 "\n"
2598 "#ifdef USEDIFFUSE\n"
2599 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2600 "#else\n"
2601 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2602 "#endif\n"
2603 "#ifdef USESPECULAR\n"
2604 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2605 "#else\n"
2606 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2607 "#endif\n"
2608 "\n"
2609 "# ifdef USECUBEFILTER\n"
2610 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2611 "       gl_FragData0.rgb *= cubecolor;\n"
2612 "       gl_FragData1.rgb *= cubecolor;\n"
2613 "# endif\n"
2614 "}\n"
2615 "#endif // FRAGMENT_SHADER\n"
2616 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2617 "\n"
2618 "\n"
2619 "\n"
2620 "\n"
2621 "#ifdef VERTEX_SHADER\n"
2622 "void main\n"
2623 "(\n"
2624 "float4 gl_Vertex : POSITION,\n"
2625 "uniform float4x4 ModelViewProjectionMatrix,\n"
2626 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2627 "float4 gl_Color : COLOR0,\n"
2628 "#endif\n"
2629 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2630 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2631 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2632 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2633 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2634 "\n"
2635 "uniform float3 EyePosition,\n"
2636 "uniform float4x4 TexMatrix,\n"
2637 "#ifdef USEVERTEXTEXTUREBLEND\n"
2638 "uniform float4x4 BackgroundTexMatrix,\n"
2639 "#endif\n"
2640 "#ifdef MODE_LIGHTSOURCE\n"
2641 "uniform float4x4 ModelToLight,\n"
2642 "#endif\n"
2643 "#ifdef MODE_LIGHTSOURCE\n"
2644 "uniform float3 LightPosition,\n"
2645 "#endif\n"
2646 "#ifdef MODE_LIGHTDIRECTION\n"
2647 "uniform float3 LightDir,\n"
2648 "#endif\n"
2649 "uniform float4 FogPlane,\n"
2650 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2651 "uniform float3 LightPosition,\n"
2652 "#endif\n"
2653 "#ifdef USESHADOWMAPORTHO\n"
2654 "uniform float4x4 ShadowMapMatrix,\n"
2655 "#endif\n"
2656 "\n"
2657 "out float4 gl_FrontColor : COLOR,\n"
2658 "out float4 TexCoordBoth : TEXCOORD0,\n"
2659 "#ifdef USELIGHTMAP\n"
2660 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2661 "#endif\n"
2662 "#ifdef USEEYEVECTOR\n"
2663 "out float3 EyeVector : TEXCOORD2,\n"
2664 "#endif\n"
2665 "#ifdef USEREFLECTION\n"
2666 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2667 "#endif\n"
2668 "#ifdef USEFOG\n"
2669 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2670 "#endif\n"
2671 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2672 "out float3 LightVector : TEXCOORD1,\n"
2673 "#endif\n"
2674 "#ifdef MODE_LIGHTSOURCE\n"
2675 "out float3 CubeVector : TEXCOORD3,\n"
2676 "#endif\n"
2677 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2678 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2679 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2680 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2681 "#endif\n"
2682 "#ifdef USESHADOWMAPORTHO\n"
2683 "out float3 ShadowMapTC : TEXCOORD8,\n"
2684 "#endif\n"
2685 "out float4 gl_Position : POSITION\n"
2686 ")\n"
2687 "{\n"
2688 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2689 "       gl_FrontColor = gl_Color;\n"
2690 "#endif\n"
2691 "       // copy the surface texcoord\n"
2692 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2693 "#ifdef USEVERTEXTEXTUREBLEND\n"
2694 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2695 "#endif\n"
2696 "#ifdef USELIGHTMAP\n"
2697 "       TexCoordLightmap = float2(gl_MultiTexCoord4);\n"
2698 "#endif\n"
2699 "\n"
2700 "#ifdef MODE_LIGHTSOURCE\n"
2701 "       // transform vertex position into light attenuation/cubemap space\n"
2702 "       // (-1 to +1 across the light box)\n"
2703 "       CubeVector = float3(mul(ModelToLight, gl_Vertex));\n"
2704 "\n"
2705 "# ifdef USEDIFFUSE\n"
2706 "       // transform unnormalized light direction into tangent space\n"
2707 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2708 "       //  normalize it per pixel)\n"
2709 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2710 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2711 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2712 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2713 "# endif\n"
2714 "#endif\n"
2715 "\n"
2716 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2717 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2718 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2719 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2720 "#endif\n"
2721 "\n"
2722 "       // transform unnormalized eye direction into tangent space\n"
2723 "#ifdef USEEYEVECTOR\n"
2724 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2725 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2726 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2727 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2728 "#endif\n"
2729 "\n"
2730 "#ifdef USEFOG\n"
2731 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2732 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2733 "#endif\n"
2734 "\n"
2735 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2736 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2737 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2738 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2739 "#endif\n"
2740 "\n"
2741 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2742 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2743 "\n"
2744 "#ifdef USESHADOWMAPORTHO\n"
2745 "       ShadowMapTC = float3(mul(ShadowMapMatrix, gl_Position));\n"
2746 "#endif\n"
2747 "\n"
2748 "#ifdef USEREFLECTION\n"
2749 "       ModelViewProjectionPosition = gl_Position;\n"
2750 "#endif\n"
2751 "}\n"
2752 "#endif // VERTEX_SHADER\n"
2753 "\n"
2754 "\n"
2755 "\n"
2756 "\n"
2757 "#ifdef FRAGMENT_SHADER\n"
2758 "void main\n"
2759 "(\n"
2760 "#ifdef USEDEFERREDLIGHTMAP\n"
2761 "float2 Pixel : WPOS,\n"
2762 "#endif\n"
2763 "float4 gl_FrontColor : COLOR,\n"
2764 "float4 TexCoordBoth : TEXCOORD0,\n"
2765 "#ifdef USELIGHTMAP\n"
2766 "float2 TexCoordLightmap : TEXCOORD1,\n"
2767 "#endif\n"
2768 "#ifdef USEEYEVECTOR\n"
2769 "float3 EyeVector : TEXCOORD2,\n"
2770 "#endif\n"
2771 "#ifdef USEREFLECTION\n"
2772 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2773 "#endif\n"
2774 "#ifdef USEFOG\n"
2775 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2776 "#endif\n"
2777 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2778 "float3 LightVector : TEXCOORD1,\n"
2779 "#endif\n"
2780 "#ifdef MODE_LIGHTSOURCE\n"
2781 "float3 CubeVector : TEXCOORD3,\n"
2782 "#endif\n"
2783 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2784 "float4 ModelViewPosition : TEXCOORD0,\n"
2785 "#endif\n"
2786 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2787 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2788 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2789 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2790 "#endif\n"
2791 "#ifdef USESHADOWMAPORTHO\n"
2792 "float3 ShadowMapTC : TEXCOORD8,\n"
2793 "#endif\n"
2794 "\n"
2795 "uniform sampler2D Texture_Normal,\n"
2796 "uniform sampler2D Texture_Color,\n"
2797 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2798 "uniform sampler2D Texture_Gloss,\n"
2799 "#endif\n"
2800 "#ifdef USEGLOW\n"
2801 "uniform sampler2D Texture_Glow,\n"
2802 "#endif\n"
2803 "#ifdef USEVERTEXTEXTUREBLEND\n"
2804 "uniform sampler2D Texture_SecondaryNormal,\n"
2805 "uniform sampler2D Texture_SecondaryColor,\n"
2806 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2807 "uniform sampler2D Texture_SecondaryGloss,\n"
2808 "#endif\n"
2809 "#ifdef USEGLOW\n"
2810 "uniform sampler2D Texture_SecondaryGlow,\n"
2811 "#endif\n"
2812 "#endif\n"
2813 "#ifdef USECOLORMAPPING\n"
2814 "uniform sampler2D Texture_Pants,\n"
2815 "uniform sampler2D Texture_Shirt,\n"
2816 "#endif\n"
2817 "#ifdef USEFOG\n"
2818 "uniform sampler2D Texture_FogMask,\n"
2819 "#endif\n"
2820 "#ifdef USELIGHTMAP\n"
2821 "uniform sampler2D Texture_Lightmap,\n"
2822 "#endif\n"
2823 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2824 "uniform sampler2D Texture_Deluxemap,\n"
2825 "#endif\n"
2826 "#ifdef USEREFLECTION\n"
2827 "uniform sampler2D Texture_Reflection,\n"
2828 "#endif\n"
2829 "\n"
2830 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2831 "uniform sampler2D Texture_ScreenDepth,\n"
2832 "uniform sampler2D Texture_ScreenNormalMap,\n"
2833 "#endif\n"
2834 "#ifdef USEDEFERREDLIGHTMAP\n"
2835 "uniform sampler2D Texture_ScreenDiffuse,\n"
2836 "uniform sampler2D Texture_ScreenSpecular,\n"
2837 "#endif\n"
2838 "\n"
2839 "#ifdef USECOLORMAPPING\n"
2840 "uniform half3 Color_Pants,\n"
2841 "uniform half3 Color_Shirt,\n"
2842 "#endif\n"
2843 "#ifdef USEFOG\n"
2844 "uniform float3 FogColor,\n"
2845 "uniform float FogRangeRecip,\n"
2846 "uniform float FogPlaneViewDist,\n"
2847 "uniform float FogHeightFade,\n"
2848 "#endif\n"
2849 "\n"
2850 "#ifdef USEOFFSETMAPPING\n"
2851 "uniform float OffsetMapping_Scale,\n"
2852 "#endif\n"
2853 "\n"
2854 "#ifdef USEDEFERREDLIGHTMAP\n"
2855 "uniform half2 PixelToScreenTexCoord,\n"
2856 "uniform half3 DeferredMod_Diffuse,\n"
2857 "uniform half3 DeferredMod_Specular,\n"
2858 "#endif\n"
2859 "uniform half3 Color_Ambient,\n"
2860 "uniform half3 Color_Diffuse,\n"
2861 "uniform half3 Color_Specular,\n"
2862 "uniform half SpecularPower,\n"
2863 "#ifdef USEGLOW\n"
2864 "uniform half3 Color_Glow,\n"
2865 "#endif\n"
2866 "uniform half Alpha,\n"
2867 "#ifdef USEREFLECTION\n"
2868 "uniform float4 DistortScaleRefractReflect,\n"
2869 "uniform float4 ScreenScaleRefractReflect,\n"
2870 "uniform float4 ScreenCenterRefractReflect,\n"
2871 "uniform half4 ReflectColor,\n"
2872 "#endif\n"
2873 "#ifdef USEREFLECTCUBE\n"
2874 "uniform float4x4 ModelToReflectCube,\n"
2875 "uniform sampler2D Texture_ReflectMask,\n"
2876 "uniform samplerCUBE Texture_ReflectCube,\n"
2877 "#endif\n"
2878 "#ifdef MODE_LIGHTDIRECTION\n"
2879 "uniform half3 LightColor,\n"
2880 "#endif\n"
2881 "#ifdef MODE_LIGHTSOURCE\n"
2882 "uniform half3 LightColor,\n"
2883 "#endif\n"
2884 "\n"
2885 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2886 "uniform sampler2D Texture_Attenuation,\n"
2887 "uniform samplerCUBE Texture_Cube,\n"
2888 "#endif\n"
2889 "\n"
2890 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2891 "\n"
2892 "#ifdef USESHADOWMAPRECT\n"
2893 "# ifdef USESHADOWSAMPLER\n"
2894 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2895 "# else\n"
2896 "uniform samplerRECT Texture_ShadowMapRect,\n"
2897 "# endif\n"
2898 "#endif\n"
2899 "\n"
2900 "#ifdef USESHADOWMAP2D\n"
2901 "# ifdef USESHADOWSAMPLER\n"
2902 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2903 "# else\n"
2904 "uniform sampler2D Texture_ShadowMap2D,\n"
2905 "# endif\n"
2906 "#endif\n"
2907 "\n"
2908 "#ifdef USESHADOWMAPVSDCT\n"
2909 "uniform samplerCUBE Texture_CubeProjection,\n"
2910 "#endif\n"
2911 "\n"
2912 "#ifdef USESHADOWMAPCUBE\n"
2913 "# ifdef USESHADOWSAMPLER\n"
2914 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2915 "# else\n"
2916 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2917 "# endif\n"
2918 "#endif\n"
2919 "\n"
2920 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2921 "uniform float2 ShadowMap_TextureScale,\n"
2922 "uniform float4 ShadowMap_Parameters,\n"
2923 "#endif\n"
2924 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2925 "\n"
2926 "out float4 gl_FragColor : COLOR\n"
2927 ")\n"
2928 "{\n"
2929 "       float2 TexCoord = TexCoordBoth.xy;\n"
2930 "#ifdef USEVERTEXTEXTUREBLEND\n"
2931 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
2932 "#endif\n"
2933 "#ifdef USEOFFSETMAPPING\n"
2934 "       // apply offsetmapping\n"
2935 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2936 "#define TexCoord TexCoordOffset\n"
2937 "#endif\n"
2938 "\n"
2939 "       // combine the diffuse textures (base, pants, shirt)\n"
2940 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
2941 "#ifdef USEALPHAKILL\n"
2942 "       if (color.a < 0.5)\n"
2943 "               discard;\n"
2944 "#endif\n"
2945 "       color.a *= Alpha;\n"
2946 "#ifdef USECOLORMAPPING\n"
2947 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord)) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
2948 "#endif\n"
2949 "#ifdef USEVERTEXTEXTUREBLEND\n"
2950 "       float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
2951 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
2952 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
2953 "       color.rgb = half3(lerp(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
2954 "       color.a = 1.0;\n"
2955 "       //color = lerp(half4(1, 0, 0, 1), color, terrainblend);\n"
2956 "#endif\n"
2957 "\n"
2958 "       // get the surface normal\n"
2959 "#ifdef USEVERTEXTEXTUREBLEND\n"
2960 "       half3 surfacenormal = normalize(half3(lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
2961 "#else\n"
2962 "       half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
2963 "#endif\n"
2964 "\n"
2965 "       // get the material colors\n"
2966 "       half3 diffusetex = color.rgb;\n"
2967 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2968 "# ifdef USEVERTEXTEXTUREBLEND\n"
2969 "       half4 glosstex = half4(lerp(float4(tex2D(Texture_SecondaryGloss, TexCoord2)), float4(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
2970 "# else\n"
2971 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
2972 "# endif\n"
2973 "#endif\n"
2974 "\n"
2975 "#ifdef USEREFLECTCUBE\n"
2976 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
2977 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
2978 "       float3 ReflectCubeTexCoord = float3(mul(ModelToReflectCube, float4(ModelReflectVector, 0)));\n"
2979 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord)) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord));\n"
2980 "#endif\n"
2981 "\n"
2982 "\n"
2983 "\n"
2984 "\n"
2985 "#ifdef MODE_LIGHTSOURCE\n"
2986 "       // light source\n"
2987 "#ifdef USEDIFFUSE\n"
2988 "       half3 lightnormal = half3(normalize(LightVector));\n"
2989 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2990 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
2991 "#ifdef USESPECULAR\n"
2992 "#ifdef USEEXACTSPECULARMATH\n"
2993 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
2994 "#else\n"
2995 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
2996 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
2997 "#endif\n"
2998 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
2999 "#endif\n"
3000 "#else\n"
3001 "       color.rgb = diffusetex * Color_Ambient;\n"
3002 "#endif\n"
3003 "       color.rgb *= LightColor;\n"
3004 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
3005 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
3006 "       color.rgb *= ShadowMapCompare(CubeVector,\n"
3007 "# if defined(USESHADOWMAP2D)\n"
3008 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3009 "# endif\n"
3010 "# if defined(USESHADOWMAPRECT)\n"
3011 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3012 "# endif\n"
3013 "# if defined(USESHADOWMAPCUBE)\n"
3014 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
3015 "# endif\n"
3016 "\n"
3017 "#ifdef USESHADOWMAPVSDCT\n"
3018 ", Texture_CubeProjection\n"
3019 "#endif\n"
3020 "       );\n"
3021 "\n"
3022 "#endif\n"
3023 "# ifdef USECUBEFILTER\n"
3024 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector));\n"
3025 "# endif\n"
3026 "#endif // MODE_LIGHTSOURCE\n"
3027 "\n"
3028 "\n"
3029 "\n"
3030 "\n"
3031 "#ifdef MODE_LIGHTDIRECTION\n"
3032 "#define SHADING\n"
3033 "#ifdef USEDIFFUSE\n"
3034 "       half3 lightnormal = half3(normalize(LightVector));\n"
3035 "#endif\n"
3036 "#define lightcolor LightColor\n"
3037 "#endif // MODE_LIGHTDIRECTION\n"
3038 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3039 "#define SHADING\n"
3040 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3041 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3042 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3043 "       // convert modelspace light vector to tangentspace\n"
3044 "       half3 lightnormal;\n"
3045 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3046 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3047 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3048 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3049 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3050 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3051 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3052 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3053 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3054 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3055 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3056 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3057 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3058 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3059 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3060 "#define SHADING\n"
3061 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3062 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3063 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3064 "#endif\n"
3065 "\n"
3066 "\n"
3067 "\n"
3068 "\n"
3069 "#ifdef MODE_LIGHTMAP\n"
3070 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
3071 "#endif // MODE_LIGHTMAP\n"
3072 "#ifdef MODE_VERTEXCOLOR\n"
3073 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3074 "#endif // MODE_VERTEXCOLOR\n"
3075 "#ifdef MODE_FLATCOLOR\n"
3076 "       color.rgb = diffusetex * Color_Ambient;\n"
3077 "#endif // MODE_FLATCOLOR\n"
3078 "\n"
3079 "\n"
3080 "\n"
3081 "\n"
3082 "#ifdef SHADING\n"
3083 "# ifdef USEDIFFUSE\n"
3084 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3085 "#  ifdef USESPECULAR\n"
3086 "#   ifdef USEEXACTSPECULARMATH\n"
3087 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
3088 "#   else\n"
3089 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3090 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
3091 "#   endif\n"
3092 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3093 "#  else\n"
3094 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3095 "#  endif\n"
3096 "# else\n"
3097 "       color.rgb = diffusetex * Color_Ambient;\n"
3098 "# endif\n"
3099 "#endif\n"
3100 "\n"
3101 "#ifdef USESHADOWMAPORTHO\n"
3102 "       color.rgb *= ShadowMapCompare(ShadowMapTC,\n"
3103 "# if defined(USESHADOWMAP2D)\n"
3104 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3105 "# endif\n"
3106 "# if defined(USESHADOWMAPRECT)\n"
3107 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3108 "# endif\n"
3109 "       );\n"
3110 "#endif\n"
3111 "\n"
3112 "#ifdef USEDEFERREDLIGHTMAP\n"
3113 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3114 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
3115 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
3116 "#endif\n"
3117 "\n"
3118 "#ifdef USEGLOW\n"
3119 "#ifdef USEVERTEXTEXTUREBLEND\n"
3120 "       color.rgb += lerp(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
3121 "#else\n"
3122 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
3123 "#endif\n"
3124 "#endif\n"
3125 "\n"
3126 "#ifdef USEFOG\n"
3127 "#ifdef MODE_LIGHTSOURCE\n"
3128 "       color.rgb *= half(FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3129 "#else\n"
3130 "       color.rgb = lerp(FogColor, float3(color.rgb), FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3131 "#endif\n"
3132 "#endif\n"
3133 "\n"
3134 "       // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
3135 "#ifdef USEREFLECTION\n"
3136 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3137 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3138 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3139 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
3140 "       // FIXME temporary hack to detect the case that the reflection\n"
3141 "       // gets blackened at edges due to leaving the area that contains actual\n"
3142 "       // content.\n"
3143 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3144 "       // 'appening.\n"
3145 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3146 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3147 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3148 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3149 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3150 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
3151 "#endif\n"
3152 "\n"
3153 "       gl_FragColor = float4(color);\n"
3154 "}\n"
3155 "#endif // FRAGMENT_SHADER\n"
3156 "\n"
3157 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3158 "#endif // !MODE_DEFERREDGEOMETRY\n"
3159 "#endif // !MODE_WATER\n"
3160 "#endif // !MODE_REFRACTION\n"
3161 "#endif // !MODE_BLOOMBLUR\n"
3162 "#endif // !MODE_GENERIC\n"
3163 "#endif // !MODE_POSTPROCESS\n"
3164 "#endif // !MODE_SHOWDEPTH\n"
3165 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3166 ;
3167
3168 char *glslshaderstring = NULL;
3169 char *cgshaderstring = NULL;
3170
3171 //=======================================================================================================================================================
3172
3173 typedef struct shaderpermutationinfo_s
3174 {
3175         const char *pretext;
3176         const char *name;
3177 }
3178 shaderpermutationinfo_t;
3179
3180 typedef struct shadermodeinfo_s
3181 {
3182         const char *vertexfilename;
3183         const char *geometryfilename;
3184         const char *fragmentfilename;
3185         const char *pretext;
3186         const char *name;
3187 }
3188 shadermodeinfo_t;
3189
3190 typedef enum shaderpermutation_e
3191 {
3192         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3193         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3194         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3195         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3196         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3197         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3198         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3199         SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
3200         SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
3201         SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
3202         SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
3203         SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
3204         SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
3205         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3206         SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3207         SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3208         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3209         SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
3210         SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
3211         SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
3212         SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
3213         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3214         SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
3215         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3216         SHADERPERMUTATION_SHADOWMAPORTHO = 1<<24, //< (lightsource) use orthographic shadowmap projection
3217         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<25, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3218         SHADERPERMUTATION_ALPHAKILL = 1<<26, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3219         SHADERPERMUTATION_REFLECTCUBE = 1<<27, ///< fake reflections using global cubemap (not HDRI light probe)
3220         SHADERPERMUTATION_LIMIT = 1<<28, ///< size of permutations array
3221         SHADERPERMUTATION_COUNT = 28 ///< size of shaderpermutationinfo array
3222 }
3223 shaderpermutation_t;
3224
3225 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3226 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3227 {
3228         {"#define USEDIFFUSE\n", " diffuse"},
3229         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3230         {"#define USEVIEWTINT\n", " viewtint"},
3231         {"#define USECOLORMAPPING\n", " colormapping"},
3232         {"#define USESATURATION\n", " saturation"},
3233         {"#define USEFOGINSIDE\n", " foginside"},
3234         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3235         {"#define USEGAMMARAMPS\n", " gammaramps"},
3236         {"#define USECUBEFILTER\n", " cubefilter"},
3237         {"#define USEGLOW\n", " glow"},
3238         {"#define USEBLOOM\n", " bloom"},
3239         {"#define USESPECULAR\n", " specular"},
3240         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3241         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3242         {"#define USEREFLECTION\n", " reflection"},
3243         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3244         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3245         {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3246         {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3247         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3248         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3249         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3250         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3251         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3252         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3253         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3254         {"#define USEALPHAKILL\n", " alphakill"},
3255         {"#define USEREFLECTCUBE\n", " reflectcube"},
3256 };
3257
3258 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3259 typedef enum shadermode_e
3260 {
3261         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3262         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3263         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3264         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3265         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3266         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3267         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3268         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3269         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3270         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3271         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3272         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3273         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3274         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3275         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3276         SHADERMODE_COUNT
3277 }
3278 shadermode_t;
3279
3280 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3281 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3282 {
3283         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3284         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3285         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3286         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3287         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3288         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3289         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3290         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3291         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3292         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3293         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3294         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3295         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3296         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3297         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3298 };
3299
3300 #ifdef SUPPORTCG
3301 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3302 {
3303         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3304         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3305         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3306         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3307         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3308         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3309         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3310         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3311         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3312         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3313         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3314         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3315         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3316         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3317         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3318 };
3319 #endif
3320
3321 struct r_glsl_permutation_s;
3322 typedef struct r_glsl_permutation_s
3323 {
3324         /// hash lookup data
3325         struct r_glsl_permutation_s *hashnext;
3326         unsigned int mode;
3327         unsigned int permutation;
3328
3329         /// indicates if we have tried compiling this permutation already
3330         qboolean compiled;
3331         /// 0 if compilation failed
3332         int program;
3333         /// locations of detected uniforms in program object, or -1 if not found
3334         int loc_Texture_First;
3335         int loc_Texture_Second;
3336         int loc_Texture_GammaRamps;
3337         int loc_Texture_Normal;
3338         int loc_Texture_Color;
3339         int loc_Texture_Gloss;
3340         int loc_Texture_Glow;
3341         int loc_Texture_SecondaryNormal;
3342         int loc_Texture_SecondaryColor;
3343         int loc_Texture_SecondaryGloss;
3344         int loc_Texture_SecondaryGlow;
3345         int loc_Texture_Pants;
3346         int loc_Texture_Shirt;
3347         int loc_Texture_FogMask;
3348         int loc_Texture_Lightmap;
3349         int loc_Texture_Deluxemap;
3350         int loc_Texture_Attenuation;
3351         int loc_Texture_Cube;
3352         int loc_Texture_Refraction;
3353         int loc_Texture_Reflection;
3354         int loc_Texture_ShadowMapRect;
3355         int loc_Texture_ShadowMapCube;
3356         int loc_Texture_ShadowMap2D;
3357         int loc_Texture_CubeProjection;
3358         int loc_Texture_ScreenDepth;
3359         int loc_Texture_ScreenNormalMap;
3360         int loc_Texture_ScreenDiffuse;
3361         int loc_Texture_ScreenSpecular;
3362         int loc_Texture_ReflectMask;
3363         int loc_Texture_ReflectCube;
3364         int loc_Alpha;
3365         int loc_BloomBlur_Parameters;
3366         int loc_ClientTime;
3367         int loc_Color_Ambient;
3368         int loc_Color_Diffuse;
3369         int loc_Color_Specular;
3370         int loc_Color_Glow;
3371         int loc_Color_Pants;
3372         int loc_Color_Shirt;
3373         int loc_DeferredColor_Ambient;
3374         int loc_DeferredColor_Diffuse;
3375         int loc_DeferredColor_Specular;
3376         int loc_DeferredMod_Diffuse;
3377         int loc_DeferredMod_Specular;
3378         int loc_DistortScaleRefractReflect;
3379         int loc_EyePosition;
3380         int loc_FogColor;
3381         int loc_FogHeightFade;
3382         int loc_FogPlane;
3383         int loc_FogPlaneViewDist;
3384         int loc_FogRangeRecip;
3385         int loc_LightColor;
3386         int loc_LightDir;
3387         int loc_LightPosition;
3388         int loc_OffsetMapping_Scale;
3389         int loc_PixelSize;
3390         int loc_ReflectColor;
3391         int loc_ReflectFactor;
3392         int loc_ReflectOffset;
3393         int loc_RefractColor;
3394         int loc_Saturation;
3395         int loc_ScreenCenterRefractReflect;
3396         int loc_ScreenScaleRefractReflect;
3397         int loc_ScreenToDepth;
3398         int loc_ShadowMap_Parameters;
3399         int loc_ShadowMap_TextureScale;
3400         int loc_SpecularPower;
3401         int loc_UserVec1;
3402         int loc_UserVec2;
3403         int loc_UserVec3;
3404         int loc_UserVec4;
3405         int loc_ViewTintColor;
3406         int loc_ViewToLight;
3407         int loc_ModelToLight;
3408         int loc_TexMatrix;
3409         int loc_BackgroundTexMatrix;
3410         int loc_ModelViewProjectionMatrix;
3411         int loc_ModelViewMatrix;
3412         int loc_PixelToScreenTexCoord;
3413         int loc_ModelToReflectCube;
3414         int loc_ShadowMapMatrix;        
3415 }
3416 r_glsl_permutation_t;
3417
3418 #define SHADERPERMUTATION_HASHSIZE 256
3419
3420 /// information about each possible shader permutation
3421 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3422 /// currently selected permutation
3423 r_glsl_permutation_t *r_glsl_permutation;
3424 /// storage for permutations linked in the hash table
3425 memexpandablearray_t r_glsl_permutationarray;
3426
3427 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3428 {
3429         //unsigned int hashdepth = 0;
3430         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3431         r_glsl_permutation_t *p;
3432         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3433         {
3434                 if (p->mode == mode && p->permutation == permutation)
3435                 {
3436                         //if (hashdepth > 10)
3437                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3438                         return p;
3439                 }
3440                 //hashdepth++;
3441         }
3442         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3443         p->mode = mode;
3444         p->permutation = permutation;
3445         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3446         r_glsl_permutationhash[mode][hashindex] = p;
3447         //if (hashdepth > 10)
3448         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3449         return p;
3450 }
3451
3452 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3453 {
3454         char *shaderstring;
3455         if (!filename || !filename[0])
3456                 return NULL;
3457         if (!strcmp(filename, "glsl/default.glsl"))
3458         {
3459                 if (!glslshaderstring)
3460                 {
3461                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3462                         if (glslshaderstring)
3463                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3464                         else
3465                                 glslshaderstring = (char *)builtinshaderstring;
3466                 }
3467                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3468                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3469                 return shaderstring;
3470         }
3471         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3472         if (shaderstring)
3473         {
3474                 if (printfromdisknotice)
3475                         Con_DPrintf("from disk %s... ", filename);
3476                 return shaderstring;
3477         }
3478         return shaderstring;
3479 }
3480
3481 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3482 {
3483         int i;
3484         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3485         int vertstrings_count = 0;
3486         int geomstrings_count = 0;
3487         int fragstrings_count = 0;
3488         char *vertexstring, *geometrystring, *fragmentstring;
3489         const char *vertstrings_list[32+3];
3490         const char *geomstrings_list[32+3];
3491         const char *fragstrings_list[32+3];
3492         char permutationname[256];
3493
3494         if (p->compiled)
3495                 return;
3496         p->compiled = true;
3497         p->program = 0;
3498
3499         permutationname[0] = 0;
3500         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3501         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3502         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3503
3504         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3505
3506         // the first pretext is which type of shader to compile as
3507         // (later these will all be bound together as a program object)
3508         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3509         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3510         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3511
3512         // the second pretext is the mode (for example a light source)
3513         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3514         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3515         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3516         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3517
3518         // now add all the permutation pretexts
3519         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3520         {
3521                 if (permutation & (1<<i))
3522                 {
3523                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3524                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3525                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3526                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3527                 }
3528                 else
3529                 {
3530                         // keep line numbers correct
3531                         vertstrings_list[vertstrings_count++] = "\n";
3532                         geomstrings_list[geomstrings_count++] = "\n";
3533                         fragstrings_list[fragstrings_count++] = "\n";
3534                 }
3535         }
3536
3537         // now append the shader text itself
3538         vertstrings_list[vertstrings_count++] = vertexstring;
3539         geomstrings_list[geomstrings_count++] = geometrystring;
3540         fragstrings_list[fragstrings_count++] = fragmentstring;
3541
3542         // if any sources were NULL, clear the respective list
3543         if (!vertexstring)
3544                 vertstrings_count = 0;
3545         if (!geometrystring)
3546                 geomstrings_count = 0;
3547         if (!fragmentstring)
3548                 fragstrings_count = 0;
3549
3550         // compile the shader program
3551         if (vertstrings_count + geomstrings_count + fragstrings_count)
3552                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3553         if (p->program)
3554         {
3555                 CHECKGLERROR
3556                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3557                 // look up all the uniform variable names we care about, so we don't
3558                 // have to look them up every time we set them
3559
3560                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3561                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3562                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3563                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3564                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3565                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3566                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3567                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3568                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3569                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3570                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3571                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3572                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3573                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3574                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3575                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3576                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3577                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3578                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3579                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3580                 p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3581                 p->loc_Texture_ShadowMapCube      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3582                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3583                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3584                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3585                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3586                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3587                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3588                 p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3589                 p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3590                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3591                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3592                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3593                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3594                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3595                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3596                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3597                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3598                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3599                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3600                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3601                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3602                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3603                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3604                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3605                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3606                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3607                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3608                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3609                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3610                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3611                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3612                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3613                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3614                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3615                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3616                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3617                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3618                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3619                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3620                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3621                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3622                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3623                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3624                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3625                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3626                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3627                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3628                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3629                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3630                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3631                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3632                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3633                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3634                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3635                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3636                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3637                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3638                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3639                 p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3640                 p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");            
3641                 // initialize the samplers to refer to the texture units we use
3642                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3643                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3644                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3645                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3646                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3647                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3648                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3649                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3650                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3651                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3652                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3653                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3654                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3655                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3656                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3657                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3658                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3659                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3660                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3661                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3662                 if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT);
3663                 if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
3664                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D);
3665                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3666                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3667                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3668                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3669                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3670                 if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
3671                 if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
3672                 CHECKGLERROR
3673                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3674         }
3675         else
3676                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3677
3678         // free the strings
3679         if (vertexstring)
3680                 Mem_Free(vertexstring);
3681         if (geometrystring)
3682                 Mem_Free(geometrystring);
3683         if (fragmentstring)
3684                 Mem_Free(fragmentstring);
3685 }
3686
3687 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3688 {
3689         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3690         if (r_glsl_permutation != perm)
3691         {
3692                 r_glsl_permutation = perm;
3693                 if (!r_glsl_permutation->program)
3694                 {
3695                         if (!r_glsl_permutation->compiled)
3696                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3697                         if (!r_glsl_permutation->program)
3698                         {
3699                                 // remove features until we find a valid permutation
3700                                 int i;
3701                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3702                                 {
3703                                         // reduce i more quickly whenever it would not remove any bits
3704                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3705                                         if (!(permutation & j))
3706                                                 continue;
3707                                         permutation -= j;
3708                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3709                                         if (!r_glsl_permutation->compiled)
3710                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3711                                         if (r_glsl_permutation->program)
3712                                                 break;
3713                                 }
3714                                 if (i >= SHADERPERMUTATION_COUNT)
3715                                 {
3716                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3717                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3718                                         qglUseProgramObjectARB(0);CHECKGLERROR
3719                                         return; // no bit left to clear, entire mode is broken
3720                                 }
3721                         }
3722                 }
3723                 CHECKGLERROR
3724                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3725         }
3726         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3727         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3728         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3729 }
3730
3731 #ifdef SUPPORTCG
3732 #include <Cg/cgGL.h>
3733 struct r_cg_permutation_s;
3734 typedef struct r_cg_permutation_s
3735 {
3736         /// hash lookup data
3737         struct r_cg_permutation_s *hashnext;
3738         unsigned int mode;
3739         unsigned int permutation;
3740
3741         /// indicates if we have tried compiling this permutation already
3742         qboolean compiled;
3743         /// 0 if compilation failed
3744         CGprogram vprogram;
3745         CGprogram fprogram;
3746         /// locations of detected parameters in programs, or NULL if not found
3747         CGparameter vp_EyePosition;
3748         CGparameter vp_FogPlane;
3749         CGparameter vp_LightDir;
3750         CGparameter vp_LightPosition;
3751         CGparameter vp_ModelToLight;
3752         CGparameter vp_TexMatrix;
3753         CGparameter vp_BackgroundTexMatrix;
3754         CGparameter vp_ModelViewProjectionMatrix;
3755         CGparameter vp_ModelViewMatrix;
3756         CGparameter vp_ShadowMapMatrix;
3757
3758         CGparameter fp_Texture_First;
3759         CGparameter fp_Texture_Second;
3760         CGparameter fp_Texture_GammaRamps;
3761         CGparameter fp_Texture_Normal;
3762         CGparameter fp_Texture_Color;
3763         CGparameter fp_Texture_Gloss;
3764         CGparameter fp_Texture_Glow;
3765         CGparameter fp_Texture_SecondaryNormal;
3766         CGparameter fp_Texture_SecondaryColor;
3767         CGparameter fp_Texture_SecondaryGloss;
3768         CGparameter fp_Texture_SecondaryGlow;
3769         CGparameter fp_Texture_Pants;
3770         CGparameter fp_Texture_Shirt;
3771         CGparameter fp_Texture_FogMask;
3772         CGparameter fp_Texture_Lightmap;
3773         CGparameter fp_Texture_Deluxemap;
3774         CGparameter fp_Texture_Attenuation;
3775         CGparameter fp_Texture_Cube;
3776         CGparameter fp_Texture_Refraction;
3777         CGparameter fp_Texture_Reflection;
3778         CGparameter fp_Texture_ShadowMapRect;
3779         CGparameter fp_Texture_ShadowMapCube;
3780         CGparameter fp_Texture_ShadowMap2D;
3781         CGparameter fp_Texture_CubeProjection;
3782         CGparameter fp_Texture_ScreenDepth;
3783         CGparameter fp_Texture_ScreenNormalMap;
3784         CGparameter fp_Texture_ScreenDiffuse;
3785         CGparameter fp_Texture_ScreenSpecular;
3786         CGparameter fp_Texture_ReflectMask;
3787         CGparameter fp_Texture_ReflectCube;
3788         CGparameter fp_Alpha;
3789         CGparameter fp_BloomBlur_Parameters;
3790         CGparameter fp_ClientTime;
3791         CGparameter fp_Color_Ambient;
3792         CGparameter fp_Color_Diffuse;
3793         CGparameter fp_Color_Specular;
3794         CGparameter fp_Color_Glow;
3795         CGparameter fp_Color_Pants;
3796         CGparameter fp_Color_Shirt;
3797         CGparameter fp_DeferredColor_Ambient;
3798         CGparameter fp_DeferredColor_Diffuse;
3799         CGparameter fp_DeferredColor_Specular;
3800         CGparameter fp_DeferredMod_Diffuse;
3801         CGparameter fp_DeferredMod_Specular;
3802         CGparameter fp_DistortScaleRefractReflect;
3803         CGparameter fp_EyePosition;
3804         CGparameter fp_FogColor;
3805         CGparameter fp_FogHeightFade;
3806         CGparameter fp_FogPlane;
3807         CGparameter fp_FogPlaneViewDist;
3808         CGparameter fp_FogRangeRecip;
3809         CGparameter fp_LightColor;
3810         CGparameter fp_LightDir;
3811         CGparameter fp_LightPosition;
3812         CGparameter fp_OffsetMapping_Scale;
3813         CGparameter fp_PixelSize;
3814         CGparameter fp_ReflectColor;
3815         CGparameter fp_ReflectFactor;
3816         CGparameter fp_ReflectOffset;
3817         CGparameter fp_RefractColor;
3818         CGparameter fp_Saturation;
3819         CGparameter fp_ScreenCenterRefractReflect;
3820         CGparameter fp_ScreenScaleRefractReflect;
3821         CGparameter fp_ScreenToDepth;
3822         CGparameter fp_ShadowMap_Parameters;
3823         CGparameter fp_ShadowMap_TextureScale;
3824         CGparameter fp_SpecularPower;
3825         CGparameter fp_UserVec1;
3826         CGparameter fp_UserVec2;
3827         CGparameter fp_UserVec3;
3828         CGparameter fp_UserVec4;
3829         CGparameter fp_ViewTintColor;
3830         CGparameter fp_ViewToLight;
3831         CGparameter fp_PixelToScreenTexCoord;
3832         CGparameter fp_ModelToReflectCube;
3833 }
3834 r_cg_permutation_t;
3835
3836 /// information about each possible shader permutation
3837 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3838 /// currently selected permutation
3839 r_cg_permutation_t *r_cg_permutation;
3840 /// storage for permutations linked in the hash table
3841 memexpandablearray_t r_cg_permutationarray;
3842
3843 #define CHECKCGERROR {CGerror err = cgGetError(), err2 = err;if (err){Con_Printf("%s:%i CG error %i: %s : %s\n", __FILE__, __LINE__, err, cgGetErrorString(err), cgGetLastErrorString(&err2));if (err == 1) Con_Printf("last listing:\n%s\n", cgGetLastListing(vid.cgcontext));}}
3844
3845 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3846 {
3847         //unsigned int hashdepth = 0;
3848         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3849         r_cg_permutation_t *p;
3850         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3851         {
3852                 if (p->mode == mode && p->permutation == permutation)
3853                 {
3854                         //if (hashdepth > 10)
3855                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3856                         return p;
3857                 }
3858                 //hashdepth++;
3859         }
3860         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3861         p->mode = mode;
3862         p->permutation = permutation;
3863         p->hashnext = r_cg_permutationhash[mode][hashindex];
3864         r_cg_permutationhash[mode][hashindex] = p;
3865         //if (hashdepth > 10)
3866         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3867         return p;
3868 }
3869
3870 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3871 {
3872         char *shaderstring;
3873         if (!filename || !filename[0])
3874                 return NULL;
3875         if (!strcmp(filename, "cg/default.cg"))
3876         {
3877                 if (!cgshaderstring)
3878                 {
3879                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3880                         if (cgshaderstring)
3881                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3882                         else
3883                                 cgshaderstring = (char *)builtincgshaderstring;
3884                 }
3885                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
3886                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
3887                 return shaderstring;
3888         }
3889         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3890         if (shaderstring)
3891         {
3892                 if (printfromdisknotice)
3893                         Con_DPrintf("from disk %s... ", filename);
3894                 return shaderstring;
3895         }
3896         return shaderstring;
3897 }
3898
3899 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
3900 {
3901         // TODO: load or create .fp and .vp shader files
3902 }
3903
3904 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
3905 {
3906         int i;
3907         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
3908         int vertstrings_count = 0, vertstring_length = 0;
3909         int geomstrings_count = 0, geomstring_length = 0;
3910         int fragstrings_count = 0, fragstring_length = 0;
3911         char *t;
3912         char *vertexstring, *geometrystring, *fragmentstring;
3913         char *vertstring, *geomstring, *fragstring;
3914         const char *vertstrings_list[32+3];
3915         const char *geomstrings_list[32+3];
3916         const char *fragstrings_list[32+3];
3917         char permutationname[256];
3918         char cachename[256];
3919         CGprofile vertexProfile;
3920         CGprofile fragmentProfile;
3921
3922         if (p->compiled)
3923                 return;
3924         p->compiled = true;
3925         p->vprogram = NULL;
3926         p->fprogram = NULL;
3927
3928         permutationname[0] = 0;
3929         cachename[0] = 0;
3930         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
3931         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
3932         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
3933
3934         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3935         strlcat(cachename, "cg/", sizeof(cachename));
3936
3937         // the first pretext is which type of shader to compile as
3938         // (later these will all be bound together as a program object)
3939         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3940         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3941         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3942
3943         // the second pretext is the mode (for example a light source)
3944         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3945         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3946         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3947         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3948         strlcat(cachename, modeinfo->name, sizeof(cachename));
3949
3950         // now add all the permutation pretexts
3951         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3952         {
3953                 if (permutation & (1<<i))
3954                 {
3955                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3956                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3957                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3958                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3959                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
3960                 }
3961                 else
3962                 {
3963                         // keep line numbers correct
3964                         vertstrings_list[vertstrings_count++] = "\n";
3965                         geomstrings_list[geomstrings_count++] = "\n";
3966                         fragstrings_list[fragstrings_count++] = "\n";
3967                 }
3968         }
3969
3970         // replace spaces in the cachename with _ characters
3971         for (i = 0;cachename[i];i++)
3972                 if (cachename[i] == ' ')
3973                         cachename[i] = '_';
3974
3975         // now append the shader text itself
3976         vertstrings_list[vertstrings_count++] = vertexstring;
3977         geomstrings_list[geomstrings_count++] = geometrystring;
3978         fragstrings_list[fragstrings_count++] = fragmentstring;
3979
3980         // if any sources were NULL, clear the respective list
3981         if (!vertexstring)
3982                 vertstrings_count = 0;
3983         if (!geometrystring)
3984                 geomstrings_count = 0;
3985         if (!fragmentstring)
3986                 fragstrings_count = 0;
3987
3988         vertstring_length = 0;
3989         for (i = 0;i < vertstrings_count;i++)
3990                 vertstring_length += strlen(vertstrings_list[i]);
3991         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
3992         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
3993                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
3994
3995         geomstring_length = 0;
3996         for (i = 0;i < geomstrings_count;i++)
3997                 geomstring_length += strlen(geomstrings_list[i]);
3998         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
3999         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4000                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4001
4002         fragstring_length = 0;
4003         for (i = 0;i < fragstrings_count;i++)
4004                 fragstring_length += strlen(fragstrings_list[i]);
4005         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4006         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4007                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4008
4009         CHECKGLERROR
4010         CHECKCGERROR
4011         //vertexProfile = CG_PROFILE_ARBVP1;
4012         //fragmentProfile = CG_PROFILE_ARBFP1;
4013         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4014         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4015         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4016         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4017         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4018         CHECKGLERROR
4019
4020         // try to load the cached shader, or generate one
4021         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4022
4023         // if caching failed, do a dynamic compile for now
4024         CHECKCGERROR
4025         if (vertstring[0] && !p->vprogram)
4026                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4027         CHECKCGERROR
4028         if (fragstring[0] && !p->fprogram)
4029                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4030         CHECKCGERROR
4031
4032         // look up all the uniform variable names we care about, so we don't
4033         // have to look them up every time we set them
4034         if (p->vprogram)
4035         {
4036                 CHECKCGERROR
4037                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4038                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4039                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4040                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4041                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4042                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4043                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4044                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4045                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4046                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4047                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4048                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4049                 CHECKCGERROR
4050         }
4051         if (p->fprogram)
4052         {
4053                 CHECKCGERROR
4054                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4055                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4056                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4057                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4058                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4059                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4060                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4061                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4062                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4063                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4064                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4065                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4066                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4067                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4068                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4069                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4070                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4071                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4072                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4073                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4074                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4075                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4076                 p->fp_Texture_ShadowMapRect      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
4077                 p->fp_Texture_ShadowMapCube      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
4078                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4079                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4080                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4081                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4082                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4083                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4084                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4085                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4086                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4087                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4088                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4089                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4090                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4091                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4092                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4093                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4094                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4095                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4096                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4097                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4098                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4099                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4100                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4101                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4102                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4103                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4104                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4105                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4106                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4107                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4108                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4109                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4110                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4111                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4112                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4113                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4114                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4115                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4116                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4117                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4118                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4119                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4120                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4121                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4122                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4123                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4124                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4125                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4126                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4127                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4128                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4129                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4130                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4131                 CHECKCGERROR
4132         }
4133
4134         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4135                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4136         else
4137                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4138
4139         // free the strings
4140         if (vertstring)
4141                 Mem_Free(vertstring);
4142         if (geomstring)
4143                 Mem_Free(geomstring);
4144         if (fragstring)
4145                 Mem_Free(fragstring);
4146         if (vertexstring)
4147                 Mem_Free(vertexstring);
4148         if (geometrystring)
4149                 Mem_Free(geometrystring);
4150         if (fragmentstring)
4151                 Mem_Free(fragmentstring);
4152 }
4153
4154 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4155 {
4156         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4157         CHECKGLERROR
4158         CHECKCGERROR
4159         if (r_cg_permutation != perm)
4160         {
4161                 r_cg_permutation = perm;
4162                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4163                 {
4164                         if (!r_cg_permutation->compiled)
4165                                 R_CG_CompilePermutation(perm, mode, permutation);
4166                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4167                         {
4168                                 // remove features until we find a valid permutation
4169                                 int i;
4170                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4171                                 {
4172                                         // reduce i more quickly whenever it would not remove any bits
4173                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4174                                         if (!(permutation & j))
4175                                                 continue;
4176                                         permutation -= j;
4177                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4178                                         if (!r_cg_permutation->compiled)
4179                                                 R_CG_CompilePermutation(perm, mode, permutation);
4180                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4181                                                 break;
4182                                 }
4183                                 if (i >= SHADERPERMUTATION_COUNT)
4184                                 {
4185                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4186                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4187                                         return; // no bit left to clear, entire mode is broken
4188                                 }
4189                         }
4190                 }
4191                 CHECKGLERROR
4192                 CHECKCGERROR
4193                 if (r_cg_permutation->vprogram)
4194                 {
4195                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4196                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4197                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4198                 }
4199                 else
4200                 {
4201                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4202                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4203                 }
4204                 if (r_cg_permutation->fprogram)
4205                 {
4206                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4207                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4208                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4209                 }
4210                 else
4211                 {
4212                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4213                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4214                 }
4215         }
4216         CHECKCGERROR
4217         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4218         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4219         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4220 }
4221
4222 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4223 {
4224         cgGLSetTextureParameter(param, R_GetTexture(tex));
4225         cgGLEnableTextureParameter(param);
4226 }
4227 #endif
4228
4229 void R_GLSL_Restart_f(void)
4230 {
4231         unsigned int i, limit;
4232         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4233                 Mem_Free(glslshaderstring);
4234         glslshaderstring = NULL;
4235         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4236                 Mem_Free(cgshaderstring);
4237         cgshaderstring = NULL;
4238         switch(vid.renderpath)
4239         {
4240         case RENDERPATH_GL20:
4241                 {
4242                         r_glsl_permutation_t *p;
4243                         r_glsl_permutation = NULL;
4244                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4245                         for (i = 0;i < limit;i++)
4246                         {
4247                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4248                                 {
4249                                         GL_Backend_FreeProgram(p->program);
4250                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4251                                 }
4252                         }
4253                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4254                 }
4255                 break;
4256         case RENDERPATH_CGGL:
4257 #ifdef SUPPORTCG
4258                 {
4259                         r_cg_permutation_t *p;
4260                         r_cg_permutation = NULL;
4261                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4262                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4263                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4264                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4265                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4266                         for (i = 0;i < limit;i++)
4267                         {
4268                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4269                                 {
4270                                         if (p->vprogram)
4271                                                 cgDestroyProgram(p->vprogram);
4272                                         if (p->fprogram)
4273                                                 cgDestroyProgram(p->fprogram);
4274                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4275                                 }
4276                         }
4277                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4278                 }
4279                 break;
4280 #endif
4281         case RENDERPATH_GL13:
4282         case RENDERPATH_GL11:
4283                 break;
4284         }
4285 }
4286
4287 void R_GLSL_DumpShader_f(void)
4288 {
4289         int i;
4290         qfile_t *file;
4291
4292         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4293         if (file)
4294         {
4295                 FS_Print(file, "/* The engine may define the following macros:\n");
4296                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4297                 for (i = 0;i < SHADERMODE_COUNT;i++)
4298                         FS_Print(file, glslshadermodeinfo[i].pretext);
4299                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4300                         FS_Print(file, shaderpermutationinfo[i].pretext);
4301                 FS_Print(file, "*/\n");
4302                 FS_Print(file, builtinshaderstring);
4303                 FS_Close(file);
4304                 Con_Printf("glsl/default.glsl written\n");
4305         }
4306         else
4307                 Con_Printf("failed to write to glsl/default.glsl\n");
4308
4309 #ifdef SUPPORTCG
4310         file = FS_OpenRealFile("cg/default.cg", "w", false);
4311         if (file)
4312         {
4313                 FS_Print(file, "/* The engine may define the following macros:\n");
4314                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4315                 for (i = 0;i < SHADERMODE_COUNT;i++)
4316                         FS_Print(file, cgshadermodeinfo[i].pretext);
4317                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4318                         FS_Print(file, shaderpermutationinfo[i].pretext);
4319                 FS_Print(file, "*/\n");
4320                 FS_Print(file, builtincgshaderstring);
4321                 FS_Close(file);
4322                 Con_Printf("cg/default.cg written\n");
4323         }
4324         else
4325                 Con_Printf("failed to write to cg/default.cg\n");
4326 #endif
4327 }
4328
4329 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4330 {
4331         if (!second)
4332                 texturemode = GL_MODULATE;
4333         switch (vid.renderpath)
4334         {
4335         case RENDERPATH_GL20:
4336                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
4337                 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
4338                 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, second);
4339                 break;
4340         case RENDERPATH_CGGL:
4341 #ifdef SUPPORTCG
4342                 CHECKCGERROR
4343                 R_SetupShader_SetPermutationCG(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
4344                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4345                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4346 #endif
4347                 break;
4348         case RENDERPATH_GL13:
4349                 R_Mesh_TexBind(0, first );
4350                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4351                 R_Mesh_TexBind(1, second);
4352                 if (second)
4353                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4354                 break;
4355         case RENDERPATH_GL11:
4356                 R_Mesh_TexBind(0, first );
4357                 break;
4358         }
4359 }
4360
4361 void R_SetupShader_DepthOrShadow(void)
4362 {
4363         switch (vid.renderpath)
4364         {
4365         case RENDERPATH_GL20:
4366                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4367                 break;
4368         case RENDERPATH_CGGL:
4369 #ifdef SUPPORTCG
4370                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4371 #endif
4372                 break;
4373         case RENDERPATH_GL13:
4374                 R_Mesh_TexBind(0, 0);
4375                 R_Mesh_TexBind(1, 0);
4376                 break;
4377         case RENDERPATH_GL11:
4378                 R_Mesh_TexBind(0, 0);
4379                 break;
4380         }
4381 }
4382
4383 void R_SetupShader_ShowDepth(void)
4384 {
4385         switch (vid.renderpath)
4386         {
4387         case RENDERPATH_GL20:
4388                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4389                 break;
4390         case RENDERPATH_CGGL:
4391 #ifdef SUPPORTCG
4392                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4393 #endif
4394                 break;
4395         case RENDERPATH_GL13:
4396                 break;
4397         case RENDERPATH_GL11:
4398                 break;
4399         }
4400 }
4401
4402 extern qboolean r_shadow_usingdeferredprepass;
4403 extern cvar_t r_shadow_deferred_8bitrange;
4404 extern rtexture_t *r_shadow_attenuationgradienttexture;
4405 extern rtexture_t *r_shadow_attenuation2dtexture;
4406 extern rtexture_t *r_shadow_attenuation3dtexture;
4407 extern qboolean r_shadow_usingshadowmaprect;
4408 extern qboolean r_shadow_usingshadowmapcube;
4409 extern qboolean r_shadow_usingshadowmap2d;
4410 extern qboolean r_shadow_usingshadowmaportho;
4411 extern float r_shadow_shadowmap_texturescale[2];
4412 extern float r_shadow_shadowmap_parameters[4];
4413 extern qboolean r_shadow_shadowmapvsdct;
4414 extern qboolean r_shadow_shadowmapsampler;
4415 extern int r_shadow_shadowmappcf;
4416 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4417 extern rtexture_t *r_shadow_shadowmap2dtexture;
4418 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4419 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4420 extern matrix4x4_t r_shadow_shadowmapmatrix;
4421 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4422 extern int r_shadow_prepass_width;
4423 extern int r_shadow_prepass_height;
4424 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4425 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4426 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4427 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4428 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
4429 {
4430         // select a permutation of the lighting shader appropriate to this
4431         // combination of texture, entity, light source, and fogging, only use the
4432         // minimum features necessary to avoid wasting rendering time in the
4433         // fragment shader on features that are not being used
4434         unsigned int permutation = 0;
4435         unsigned int mode = 0;
4436         float m16f[16];
4437         if (rsurfacepass == RSURFPASS_BACKGROUND)
4438         {
4439                 // distorted background
4440                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4441                         mode = SHADERMODE_WATER;
4442                 else
4443                         mode = SHADERMODE_REFRACTION;
4444                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4445                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4446                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4447                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4448                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4449                 R_Mesh_ColorPointer(NULL, 0, 0);
4450                 GL_AlphaTest(false);
4451                 GL_BlendFunc(GL_ONE, GL_ZERO);
4452         }
4453         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4454         {
4455                 if (r_glsl_offsetmapping.integer)
4456                 {
4457                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4458                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4459                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4460                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4461                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4462                         {
4463                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4464                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4465                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4466                         }
4467                 }
4468                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4469                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4470                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4471                         permutation |= SHADERPERMUTATION_ALPHAKILL;
4472                 // normalmap (deferred prepass), may use alpha test on diffuse
4473                 mode = SHADERMODE_DEFERREDGEOMETRY;
4474                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4475                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4476                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4477                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4478                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4479                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4480                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4481                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4482                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4483                 else
4484                         R_Mesh_ColorPointer(NULL, 0, 0);
4485                 GL_AlphaTest(false);
4486                 GL_BlendFunc(GL_ONE, GL_ZERO);
4487         }
4488         else if (rsurfacepass == RSURFPASS_RTLIGHT)
4489         {
4490                 if (r_glsl_offsetmapping.integer)
4491                 {
4492                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4493                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4494                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4495                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4496                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4497                         {
4498                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4499                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4500                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4501                         }
4502                 }
4503                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4504                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4505                 // light source
4506                 mode = SHADERMODE_LIGHTSOURCE;
4507                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4508                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4509                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4510                         permutation |= SHADERPERMUTATION_CUBEFILTER;
4511                 if (diffusescale > 0)
4512                         permutation |= SHADERPERMUTATION_DIFFUSE;
4513                 if (specularscale > 0)
4514                 {
4515                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4516                         if (r_shadow_glossexact.integer)
4517                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4518                 }
4519                 if (r_refdef.fogenabled)
4520                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4521                 if (rsurface.texture->colormapping)
4522                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4523                 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4524                 {
4525                         if (r_shadow_usingshadowmaprect)
4526                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4527                         if (r_shadow_usingshadowmap2d)
4528                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4529                         if (r_shadow_usingshadowmapcube)
4530                                 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4531                         else if(r_shadow_shadowmapvsdct)
4532                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4533
4534                         if (r_shadow_shadowmapsampler)
4535                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4536                         if (r_shadow_shadowmappcf > 1)
4537                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4538                         else if (r_shadow_shadowmappcf)
4539                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4540                 }
4541                 if (rsurface.texture->reflectmasktexture)
4542                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4543                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4544                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4545                 {
4546                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4547                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4548                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4549                 }
4550                 else
4551                 {
4552                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4553                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4554                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4555                 }
4556                 //R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4557                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4558                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4559                 else
4560                         R_Mesh_ColorPointer(NULL, 0, 0);
4561                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4562                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4563         }
4564         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4565         {
4566                 if (r_glsl_offsetmapping.integer)
4567                 {
4568                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4569                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4570                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4571                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4572                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4573                         {
4574                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4575                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4576                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4577                         }
4578                 }
4579                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4580                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4581                 // unshaded geometry (fullbright or ambient model lighting)
4582                 mode = SHADERMODE_FLATCOLOR;
4583                 ambientscale = diffusescale = specularscale = 0;
4584                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4585                         permutation |= SHADERPERMUTATION_GLOW;
4586                 if (r_refdef.fogenabled)
4587                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4588                 if (rsurface.texture->colormapping)
4589                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4590                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4591                 {
4592                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4593                         if (r_shadow_usingshadowmaprect)
4594                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4595                         if (r_shadow_usingshadowmap2d)
4596                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4597
4598                         if (r_shadow_shadowmapsampler)
4599                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4600                         if (r_shadow_shadowmappcf > 1)
4601                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4602                         else if (r_shadow_shadowmappcf)
4603                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4604                 }
4605                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4606                         permutation |= SHADERPERMUTATION_REFLECTION;
4607                 if (rsurface.texture->reflectmasktexture)
4608                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4609                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4610                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4611                 {
4612                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4613                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4614                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4615                 }
4616                 else
4617                 {
4618                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4619                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4620                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4621                 }
4622                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4623                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4624                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4625                 else
4626                         R_Mesh_ColorPointer(NULL, 0, 0);
4627                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4628                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4629         }
4630         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4631         {
4632                 if (r_glsl_offsetmapping.integer)
4633                 {
4634                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4635                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4636                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4637                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4638                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4639                         {
4640                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4641                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4642                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4643                         }
4644                 }
4645                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4646                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4647                 // directional model lighting
4648                 mode = SHADERMODE_LIGHTDIRECTION;
4649                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4650                         permutation |= SHADERPERMUTATION_GLOW;
4651                 permutation |= SHADERPERMUTATION_DIFFUSE;
4652                 if (specularscale > 0)
4653                 {
4654                         permutation |= SHADERPERMUTATION_SPECULAR;
4655                         if (r_shadow_glossexact.integer)
4656                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4657                 }
4658                 if (r_refdef.fogenabled)
4659                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4660                 if (rsurface.texture->colormapping)
4661                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4662                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4663                 {
4664                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4665                         if (r_shadow_usingshadowmaprect)
4666                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4667                         if (r_shadow_usingshadowmap2d)
4668                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4669
4670                         if (r_shadow_shadowmapsampler)
4671                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4672                         if (r_shadow_shadowmappcf > 1)
4673                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4674                         else if (r_shadow_shadowmappcf)
4675                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4676                 }
4677                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4678                         permutation |= SHADERPERMUTATION_REFLECTION;
4679                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4680                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4681                 if (rsurface.texture->reflectmasktexture)
4682                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4683                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4684                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4685                 {
4686                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4687                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4688                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4689                 }
4690                 else
4691                 {
4692                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4693                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4694                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4695                 }
4696                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4697                 R_Mesh_ColorPointer(NULL, 0, 0);
4698                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4699                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4700         }
4701         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
4702         {
4703                 if (r_glsl_offsetmapping.integer)
4704                 {
4705                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4706                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4707                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4708                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4709                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4710                         {
4711                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4712                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4713                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4714                         }
4715                 }
4716                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4717                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4718                 // ambient model lighting
4719                 mode = SHADERMODE_LIGHTDIRECTION;
4720                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4721                         permutation |= SHADERPERMUTATION_GLOW;
4722                 if (r_refdef.fogenabled)
4723                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4724                 if (rsurface.texture->colormapping)
4725                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4726                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4727                 {
4728                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4729                         if (r_shadow_usingshadowmaprect)
4730                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4731                         if (r_shadow_usingshadowmap2d)
4732                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4733
4734                         if (r_shadow_shadowmapsampler)
4735                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4736                         if (r_shadow_shadowmappcf > 1)
4737                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4738                         else if (r_shadow_shadowmappcf)
4739                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4740                 }
4741                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4742                         permutation |= SHADERPERMUTATION_REFLECTION;
4743                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4744                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4745                 if (rsurface.texture->reflectmasktexture)
4746                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4747                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4748                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4749                 {
4750                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4751                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4752                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4753                 }
4754                 else
4755                 {
4756                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4757                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4758                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4759                 }
4760                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4761                 R_Mesh_ColorPointer(NULL, 0, 0);
4762                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4763                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4764         }
4765         else
4766         {
4767                 if (r_glsl_offsetmapping.integer)
4768                 {
4769                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4770                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4771                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4772                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4773                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4774                         {
4775                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4776                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4777                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4778                         }
4779                 }
4780                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4781                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4782                 // lightmapped wall
4783                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4784                         permutation |= SHADERPERMUTATION_GLOW;
4785                 if (r_refdef.fogenabled)
4786                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4787                 if (rsurface.texture->colormapping)
4788                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4789                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4790                 {
4791                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4792                         if (r_shadow_usingshadowmaprect)
4793                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4794                         if (r_shadow_usingshadowmap2d)
4795                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4796
4797                         if (r_shadow_shadowmapsampler)
4798                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4799                         if (r_shadow_shadowmappcf > 1)
4800                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4801                         else if (r_shadow_shadowmappcf)
4802                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4803                 }
4804                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4805                         permutation |= SHADERPERMUTATION_REFLECTION;
4806                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4807                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4808                 if (rsurface.texture->reflectmasktexture)
4809                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4810                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
4811                 {
4812                         // deluxemapping (light direction texture)
4813                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
4814                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
4815                         else
4816                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4817                         permutation |= SHADERPERMUTATION_DIFFUSE;
4818                         if (specularscale > 0)
4819                         {
4820                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4821                                 if (r_shadow_glossexact.integer)
4822                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4823                         }
4824                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4825                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4826                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4827                         else
4828                                 R_Mesh_ColorPointer(NULL, 0, 0);
4829                 }
4830                 else if (r_glsl_deluxemapping.integer >= 2)
4831                 {
4832                         // fake deluxemapping (uniform light direction in tangentspace)
4833                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4834                         permutation |= SHADERPERMUTATION_DIFFUSE;
4835                         if (specularscale > 0)
4836                         {
4837                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4838                                 if (r_shadow_glossexact.integer)
4839                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4840                         }
4841                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4842                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4843                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4844                         else
4845                                 R_Mesh_ColorPointer(NULL, 0, 0);
4846                 }
4847                 else if (rsurface.uselightmaptexture)
4848                 {
4849                         // ordinary lightmapping (q1bsp, q3bsp)
4850                         mode = SHADERMODE_LIGHTMAP;
4851                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4852                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4853                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4854                         else
4855                                 R_Mesh_ColorPointer(NULL, 0, 0);
4856                 }
4857                 else
4858                 {
4859                         // ordinary vertex coloring (q3bsp)
4860                         mode = SHADERMODE_VERTEXCOLOR;
4861                         R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4862                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4863                 }
4864                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4865                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4866                 {
4867                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4868                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4869                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4870                 }
4871                 else
4872                 {
4873                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4874                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4875                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4876                 }
4877                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4878                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4879         }
4880         switch(vid.renderpath)
4881         {
4882         case RENDERPATH_GL20:
4883                 R_SetupShader_SetPermutationGLSL(mode, permutation);
4884                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
4885                 if (mode == SHADERMODE_LIGHTSOURCE)
4886                 {
4887                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
4888                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
4889                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
4890                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0] * ambientscale, rsurface.colormod[1] * ambientscale, rsurface.colormod[2] * ambientscale);
4891                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, rsurface.colormod[0] * diffusescale, rsurface.colormod[1] * diffusescale, rsurface.colormod[2] * diffusescale);
4892                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
4893         
4894                         // additive passes are only darkened by fog, not tinted
4895                         if (r_glsl_permutation->loc_FogColor >= 0)
4896                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4897                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4898                 }
4899                 else
4900                 {
4901                         if (mode == SHADERMODE_FLATCOLOR)
4902                         {
4903                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
4904                         }
4905                         else if (mode == SHADERMODE_LIGHTDIRECTION)
4906                         {
4907                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * rsurface.colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * rsurface.colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * rsurface.colormod[2]);
4908                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * rsurface.colormod[0], r_refdef.lightmapintensity * rsurface.colormod[1], r_refdef.lightmapintensity * rsurface.colormod[2]);
4909                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
4910                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, rsurface.colormod[0] * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * r_shadow_deferred_8bitrange.value);
4911                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
4912                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
4913                                 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
4914                         }
4915                         else
4916                         {
4917                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * rsurface.colormod[0], r_refdef.scene.ambient * rsurface.colormod[1], r_refdef.scene.ambient * rsurface.colormod[2]);
4918                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
4919                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
4920                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, rsurface.colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
4921                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
4922                         }
4923                         // additive passes are only darkened by fog, not tinted
4924                         if (r_glsl_permutation->loc_FogColor >= 0)
4925                         {
4926                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4927                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4928                                 else
4929                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4930                         }
4931                         if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
4932                         if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
4933                         if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
4934                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
4935                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
4936                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
4937                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
4938                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4939                 }
4940                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
4941                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
4942                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
4943                 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2fARB(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
4944                 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4fARB(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
4945
4946                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
4947                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
4948                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
4949                 if (r_glsl_permutation->loc_Color_Pants >= 0)
4950                 {
4951                         if (rsurface.texture->pantstexture)
4952                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4953                         else
4954                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
4955                 }
4956                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
4957                 {
4958                         if (rsurface.texture->shirttexture)
4959                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4960                         else
4961                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
4962                 }
4963                 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4fARB(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
4964                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
4965                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
4966                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
4967                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
4968                 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2fARB(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
4969                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
4970
4971         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
4972         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
4973         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
4974                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
4975                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
4976                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
4977                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
4978                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
4979                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
4980                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
4981                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
4982                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
4983                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
4984                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
4985                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
4986                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
4987                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_white                                     );
4988                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_blanknormalmap                            );
4989                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
4990                 if (r_glsl_permutation->loc_Texture_Refraction      >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , r_texture_white                                     );
4991                 if (r_glsl_permutation->loc_Texture_Reflection      >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , r_texture_white                                     );
4992                 if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
4993                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
4994                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
4995                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
4996                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
4997                 {
4998                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
4999                         if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT, r_shadow_shadowmaprectangletexture                  );
5000                         if (rsurface.rtlight)
5001                         {
5002                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5003                                 if (r_shadow_usingshadowmapcube)
5004                                         if (r_glsl_permutation->loc_Texture_ShadowMapCube   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE     , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5005                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5006                         }
5007                 }
5008                 CHECKGLERROR
5009                 break;
5010         case RENDERPATH_CGGL:
5011 #ifdef SUPPORTCG
5012                 R_SetupShader_SetPermutationCG(mode, permutation);
5013                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
5014                 if (mode == SHADERMODE_LIGHTSOURCE)
5015                 {
5016                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
5017                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5018                 }
5019                 else
5020                 {
5021                         if (mode == SHADERMODE_LIGHTDIRECTION)
5022                         {
5023                                 if (r_cg_permutation->vp_LightDir) cgGLSetParameter3f(r_cg_permutation->vp_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);CHECKCGERROR
5024                         }
5025                 }
5026                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
5027                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
5028                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
5029                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5030                 if (r_cg_permutation->vp_FogPlane) cgGLSetParameter4f(r_cg_permutation->vp_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);CHECKCGERROR
5031                 CHECKGLERROR
5032
5033                 if (mode == SHADERMODE_LIGHTSOURCE)
5034                 {
5035                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5036                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
5037                         if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0] * ambientscale, rsurface.colormod[1] * ambientscale, rsurface.colormod[2] * ambientscale);CHECKCGERROR
5038                         if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, rsurface.colormod[0] * diffusescale, rsurface.colormod[1] * diffusescale, rsurface.colormod[2] * diffusescale);CHECKCGERROR
5039                         if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);CHECKCGERROR
5040
5041                         // additive passes are only darkened by fog, not tinted
5042                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
5043                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5044                 }
5045                 else
5046                 {
5047                         if (mode == SHADERMODE_FLATCOLOR)
5048                         {
5049                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);CHECKCGERROR
5050                         }
5051                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5052                         {
5053                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * rsurface.colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * rsurface.colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * rsurface.colormod[2]);CHECKCGERROR
5054                                 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, r_refdef.lightmapintensity * rsurface.colormod[0], r_refdef.lightmapintensity * rsurface.colormod[1], r_refdef.lightmapintensity * rsurface.colormod[2]);CHECKCGERROR
5055                                 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);CHECKCGERROR
5056                                 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, rsurface.colormod[0] * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * r_shadow_deferred_8bitrange.value);CHECKCGERROR
5057                                 if (r_cg_permutation->fp_DeferredMod_Specular) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
5058                                 if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);CHECKCGERROR
5059                                 if (r_cg_permutation->fp_LightDir) cgGLSetParameter3f(r_cg_permutation->fp_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);CHECKCGERROR
5060                         }
5061                         else
5062                         {
5063                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, r_refdef.scene.ambient * rsurface.colormod[0], r_refdef.scene.ambient * rsurface.colormod[1], r_refdef.scene.ambient * rsurface.colormod[2]);CHECKCGERROR
5064                                 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);CHECKCGERROR
5065                                 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);CHECKCGERROR
5066                                 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, rsurface.colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
5067                                 if (r_cg_permutation->fp_DeferredMod_Specular) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
5068                         }
5069                         // additive passes are only darkened by fog, not tinted
5070                         if (r_cg_permutation->fp_FogColor)
5071                         {
5072                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5073                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
5074                                 else
5075                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5076                                 CHECKCGERROR
5077                         }
5078                         if (r_cg_permutation->fp_DistortScaleRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);CHECKCGERROR
5079                         if (r_cg_permutation->fp_ScreenScaleRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);CHECKCGERROR
5080                         if (r_cg_permutation->fp_ScreenCenterRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);CHECKCGERROR
5081                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
5082                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
5083                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
5084                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
5085                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5086                 }
5087                 if (r_cg_permutation->fp_ShadowMap_TextureScale) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);CHECKCGERROR
5088                 if (r_cg_permutation->fp_ShadowMap_Parameters) cgGLSetParameter4f(r_cg_permutation->fp_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);CHECKCGERROR
5089                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
5090                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
5091                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5092                 if (r_cg_permutation->fp_Color_Pants)
5093                 {
5094                         if (rsurface.texture->pantstexture)
5095                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5096                         else
5097                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
5098                         CHECKCGERROR
5099                 }
5100                 if (r_cg_permutation->fp_Color_Shirt)
5101                 {
5102                         if (rsurface.texture->shirttexture)
5103                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5104                         else
5105                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
5106                         CHECKCGERROR
5107                 }
5108                 if (r_cg_permutation->fp_FogPlane) cgGLSetParameter4f(r_cg_permutation->fp_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);CHECKCGERROR
5109                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
5110                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
5111                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
5112                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
5113                 if (r_cg_permutation->fp_ScreenToDepth) cgGLSetParameter2f(r_cg_permutation->fp_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);CHECKCGERROR
5114                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5115
5116         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
5117         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
5118         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
5119                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
5120                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
5121                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
5122                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
5123                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
5124                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
5125                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
5126                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
5127                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
5128                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
5129                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
5130                 if (r_cg_permutation->fp_Texture_ReflectCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectCube    , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);CHECKCGERROR
5131                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
5132                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , r_texture_white                                     );CHECKCGERROR
5133                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , r_texture_blanknormalmap                            );CHECKCGERROR
5134                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
5135                 if (r_cg_permutation->fp_Texture_Refraction     ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction     , r_texture_white                                     );CHECKCGERROR
5136                 if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , r_texture_white                                     );CHECKCGERROR
5137                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
5138                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
5139                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
5140                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
5141                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5142                 {
5143                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5144                         if (r_cg_permutation->fp_Texture_ShadowMapRect  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
5145                         if (rsurface.rtlight)
5146                         {
5147                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
5148                                 if (r_shadow_usingshadowmapcube)
5149                                         if (r_cg_permutation->fp_Texture_ShadowMapCube  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5150                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
5151                         }
5152                 }
5153
5154                 CHECKGLERROR
5155 #endif
5156                 break;
5157         case RENDERPATH_GL13:
5158         case RENDERPATH_GL11:
5159                 break;
5160         }
5161 }
5162
5163 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
5164 {
5165         // select a permutation of the lighting shader appropriate to this
5166         // combination of texture, entity, light source, and fogging, only use the
5167         // minimum features necessary to avoid wasting rendering time in the
5168         // fragment shader on features that are not being used
5169         unsigned int permutation = 0;
5170         unsigned int mode = 0;
5171         const float *lightcolorbase = rtlight->currentcolor;
5172         float ambientscale = rtlight->ambientscale;
5173         float diffusescale = rtlight->diffusescale;
5174         float specularscale = rtlight->specularscale;
5175         // this is the location of the light in view space
5176         vec3_t viewlightorigin;
5177         // this transforms from view space (camera) to light space (cubemap)
5178         matrix4x4_t viewtolight;
5179         matrix4x4_t lighttoview;
5180         float viewtolight16f[16];
5181         float range = 1.0f / r_shadow_deferred_8bitrange.value;
5182         // light source
5183         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
5184         if (rtlight->currentcubemap != r_texture_whitecube)
5185                 permutation |= SHADERPERMUTATION_CUBEFILTER;
5186         if (diffusescale > 0)
5187                 permutation |= SHADERPERMUTATION_DIFFUSE;
5188         if (specularscale > 0)
5189         {
5190                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5191                 if (r_shadow_glossexact.integer)
5192                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5193         }
5194         if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
5195         {
5196                 if (r_shadow_usingshadowmaprect)
5197                         permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5198                 if (r_shadow_usingshadowmap2d)
5199                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5200                 if (r_shadow_usingshadowmapcube)
5201                         permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
5202                 else if(r_shadow_shadowmapvsdct)
5203                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5204
5205                 if (r_shadow_shadowmapsampler)
5206                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5207                 if (r_shadow_shadowmappcf > 1)
5208                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5209                 else if (r_shadow_shadowmappcf)
5210                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5211         }
5212         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
5213         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
5214         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
5215         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
5216         switch(vid.renderpath)
5217         {
5218         case RENDERPATH_GL20:
5219                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5220                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5221                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
5222                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3fARB(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
5223                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3fARB(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
5224                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3fARB(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
5225                 if (r_glsl_permutation->loc_ShadowMap_TextureScale    >= 0) qglUniform2fARB(       r_glsl_permutation->loc_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5226                 if (r_glsl_permutation->loc_ShadowMap_Parameters      >= 0) qglUniform4fARB(       r_glsl_permutation->loc_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5227                 if (r_glsl_permutation->loc_SpecularPower             >= 0) qglUniform1fARB(       r_glsl_permutation->loc_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5228                 if (r_glsl_permutation->loc_ScreenToDepth             >= 0) qglUniform2fARB(       r_glsl_permutation->loc_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5229                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5230
5231                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
5232                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
5233                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
5234                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
5235                 if (r_glsl_permutation->loc_Texture_ShadowMapRect     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT      , r_shadow_shadowmaprectangletexture                  );
5236                 if (r_shadow_usingshadowmapcube)
5237                         if (r_glsl_permutation->loc_Texture_ShadowMapCube     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE      , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5238                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
5239                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
5240                 break;
5241         case RENDERPATH_CGGL:
5242 #ifdef SUPPORTCG
5243                 R_SetupShader_SetPermutationCG(mode, permutation);
5244                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
5245                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
5246                 if (r_cg_permutation->fp_DeferredColor_Ambient    ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);CHECKCGERROR
5247                 if (r_cg_permutation->fp_DeferredColor_Diffuse    ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);CHECKCGERROR
5248                 if (r_cg_permutation->fp_DeferredColor_Specular   ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);CHECKCGERROR
5249                 if (r_cg_permutation->fp_ShadowMap_TextureScale   ) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);CHECKCGERROR
5250                 if (r_cg_permutation->fp_ShadowMap_Parameters     ) cgGLSetParameter4f(r_cg_permutation->fp_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);CHECKCGERROR
5251                 if (r_cg_permutation->fp_SpecularPower            ) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5252                 if (r_cg_permutation->fp_ScreenToDepth            ) cgGLSetParameter2f(r_cg_permutation->fp_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);CHECKCGERROR
5253                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5254
5255                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
5256                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
5257                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
5258                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
5259                 if (r_cg_permutation->fp_Texture_ShadowMapRect    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
5260                 if (r_shadow_usingshadowmapcube)
5261                         if (r_cg_permutation->fp_Texture_ShadowMapCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5262                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5263                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
5264 #endif
5265                 break;
5266         case RENDERPATH_GL13:
5267         case RENDERPATH_GL11:
5268                 break;
5269         }
5270 }
5271
5272 #define SKINFRAME_HASH 1024
5273
5274 typedef struct
5275 {
5276         int loadsequence; // incremented each level change
5277         memexpandablearray_t array;
5278         skinframe_t *hash[SKINFRAME_HASH];
5279 }
5280 r_skinframe_t;
5281 r_skinframe_t r_skinframe;
5282
5283 void R_SkinFrame_PrepareForPurge(void)
5284 {
5285         r_skinframe.loadsequence++;
5286         // wrap it without hitting zero
5287         if (r_skinframe.loadsequence >= 200)
5288                 r_skinframe.loadsequence = 1;
5289 }
5290
5291 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5292 {
5293         if (!skinframe)
5294                 return;
5295         // mark the skinframe as used for the purging code
5296         skinframe->loadsequence = r_skinframe.loadsequence;
5297 }
5298
5299 void R_SkinFrame_Purge(void)
5300 {
5301         int i;
5302         skinframe_t *s;
5303         for (i = 0;i < SKINFRAME_HASH;i++)
5304         {
5305                 for (s = r_skinframe.hash[i];s;s = s->next)
5306                 {
5307                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5308                         {
5309                                 if (s->merged == s->base)
5310                                         s->merged = NULL;
5311                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5312                                 R_PurgeTexture(s->stain );s->stain  = NULL;
5313                                 R_PurgeTexture(s->merged);s->merged = NULL;
5314                                 R_PurgeTexture(s->base  );s->base   = NULL;
5315                                 R_PurgeTexture(s->pants );s->pants  = NULL;
5316                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
5317                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
5318                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
5319                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
5320                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
5321                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
5322                                 s->loadsequence = 0;
5323                         }
5324                 }
5325         }
5326 }
5327
5328 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5329         skinframe_t *item;
5330         char basename[MAX_QPATH];
5331
5332         Image_StripImageExtension(name, basename, sizeof(basename));
5333
5334         if( last == NULL ) {
5335                 int hashindex;
5336                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5337                 item = r_skinframe.hash[hashindex];
5338         } else {
5339                 item = last->next;
5340         }
5341
5342         // linearly search through the hash bucket
5343         for( ; item ; item = item->next ) {
5344                 if( !strcmp( item->basename, basename ) ) {
5345                         return item;
5346                 }
5347         }
5348         return NULL;
5349 }
5350
5351 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5352 {
5353         skinframe_t *item;
5354         int hashindex;
5355         char basename[MAX_QPATH];
5356
5357         Image_StripImageExtension(name, basename, sizeof(basename));
5358
5359         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5360         for (item = r_skinframe.hash[hashindex];item;item = item->next)
5361                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5362                         break;
5363
5364         if (!item) {
5365                 rtexture_t *dyntexture;
5366                 // check whether its a dynamic texture
5367                 dyntexture = CL_GetDynTexture( basename );
5368                 if (!add && !dyntexture)
5369                         return NULL;
5370                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5371                 memset(item, 0, sizeof(*item));
5372                 strlcpy(item->basename, basename, sizeof(item->basename));
5373                 item->base = dyntexture; // either NULL or dyntexture handle
5374                 item->textureflags = textureflags;
5375                 item->comparewidth = comparewidth;
5376                 item->compareheight = compareheight;
5377                 item->comparecrc = comparecrc;
5378                 item->next = r_skinframe.hash[hashindex];
5379                 r_skinframe.hash[hashindex] = item;
5380         }
5381         else if( item->base == NULL )
5382         {
5383                 rtexture_t *dyntexture;
5384                 // check whether its a dynamic texture
5385                 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
5386                 dyntexture = CL_GetDynTexture( basename );
5387                 item->base = dyntexture; // either NULL or dyntexture handle
5388         }
5389
5390         R_SkinFrame_MarkUsed(item);
5391         return item;
5392 }
5393
5394 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5395         { \
5396                 unsigned long long avgcolor[5], wsum; \
5397                 int pix, comp, w; \
5398                 avgcolor[0] = 0; \
5399                 avgcolor[1] = 0; \
5400                 avgcolor[2] = 0; \
5401                 avgcolor[3] = 0; \
5402                 avgcolor[4] = 0; \
5403                 wsum = 0; \
5404                 for(pix = 0; pix < cnt; ++pix) \
5405                 { \
5406                         w = 0; \
5407                         for(comp = 0; comp < 3; ++comp) \
5408                                 w += getpixel; \
5409                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5410                         { \
5411                                 ++wsum; \
5412                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5413                                 w = getpixel; \
5414                                 for(comp = 0; comp < 3; ++comp) \
5415                                         avgcolor[comp] += getpixel * w; \
5416                                 avgcolor[3] += w; \
5417                         } \
5418                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5419                         avgcolor[4] += getpixel; \
5420                 } \
5421                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5422                         avgcolor[3] = 1; \
5423                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5424                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5425                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5426                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5427         }
5428
5429 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5430 {
5431         int j;
5432         unsigned char *pixels;
5433         unsigned char *bumppixels;
5434         unsigned char *basepixels = NULL;
5435         int basepixels_width = 0;
5436         int basepixels_height = 0;
5437         skinframe_t *skinframe;
5438         rtexture_t *ddsbase = NULL;
5439         qboolean ddshasalpha = false;
5440         float ddsavgcolor[4];
5441         char basename[MAX_QPATH];
5442
5443         if (cls.state == ca_dedicated)
5444                 return NULL;
5445
5446         // return an existing skinframe if already loaded
5447         // if loading of the first image fails, don't make a new skinframe as it
5448         // would cause all future lookups of this to be missing
5449         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5450         if (skinframe && skinframe->base)
5451                 return skinframe;
5452
5453         Image_StripImageExtension(name, basename, sizeof(basename));
5454
5455         // check for DDS texture file first
5456         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor)))
5457         {
5458                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer);
5459                 if (basepixels == NULL)
5460                         return NULL;
5461         }
5462
5463         if (developer_loading.integer)
5464                 Con_Printf("loading skin \"%s\"\n", name);
5465
5466         // we've got some pixels to store, so really allocate this new texture now
5467         if (!skinframe)
5468                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5469         skinframe->stain = NULL;
5470         skinframe->merged = NULL;
5471         skinframe->base = NULL;
5472         skinframe->pants = NULL;
5473         skinframe->shirt = NULL;
5474         skinframe->nmap = NULL;
5475         skinframe->gloss = NULL;
5476         skinframe->glow = NULL;
5477         skinframe->fog = NULL;
5478         skinframe->reflect = NULL;
5479         skinframe->hasalpha = false;
5480
5481         if (ddsbase)
5482         {
5483                 skinframe->base = ddsbase;
5484                 skinframe->hasalpha = ddshasalpha;
5485                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5486                 if (r_loadfog && skinframe->hasalpha)
5487                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5488                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
5489         }
5490         else
5491         {
5492                 basepixels_width = image_width;
5493                 basepixels_height = image_height;
5494                 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
5495                 if (textureflags & TEXF_ALPHA)
5496                 {
5497                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5498                         {
5499                                 if (basepixels[j] < 255)
5500                                 {
5501                                         skinframe->hasalpha = true;
5502                                         break;
5503                                 }
5504                         }
5505                         if (r_loadfog && skinframe->hasalpha)
5506                         {
5507                                 // has transparent pixels
5508                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5509                                 for (j = 0;j < image_width * image_height * 4;j += 4)
5510                                 {
5511                                         pixels[j+0] = 255;
5512                                         pixels[j+1] = 255;
5513                                         pixels[j+2] = 255;
5514                                         pixels[j+3] = basepixels[j+3];
5515                                 }
5516                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
5517                                 Mem_Free(pixels);
5518                         }
5519                 }
5520                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5521                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
5522                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5523                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true);
5524                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
5525                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true);
5526         }
5527
5528         if (r_loaddds)
5529         {
5530                 if (r_loadnormalmap)
5531                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5532                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL);
5533                 if (r_loadgloss)
5534                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL);
5535                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL);
5536                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL);
5537                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL);
5538         }
5539
5540         // _norm is the name used by tenebrae and has been adopted as standard
5541         if (r_loadnormalmap && skinframe->nmap == NULL)
5542         {
5543                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false)) != NULL)
5544                 {
5545                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
5546                         Mem_Free(pixels);
5547                         pixels = NULL;
5548                 }
5549                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false)) != NULL)
5550                 {
5551                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5552                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5553                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
5554                         Mem_Free(pixels);
5555                         Mem_Free(bumppixels);
5556                 }
5557                 else if (r_shadow_bumpscale_basetexture.value > 0)
5558                 {
5559                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5560                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5561                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
5562                         Mem_Free(pixels);
5563                 }
5564                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
5565                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true);
5566         }
5567
5568         // _luma is supported only for tenebrae compatibility
5569         // _glow is the preferred name
5570         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer))))
5571         {
5572                 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), NULL);
5573                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
5574                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true);
5575                 Mem_Free(pixels);pixels = NULL;
5576         }
5577
5578         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5579         {
5580                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), NULL);
5581                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
5582                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true);
5583                 Mem_Free(pixels);
5584                 pixels = NULL;
5585         }
5586
5587         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5588         {
5589                 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
5590                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
5591                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true);
5592                 Mem_Free(pixels);
5593                 pixels = NULL;
5594         }
5595
5596         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5597         {
5598                 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
5599                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
5600                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true);
5601                 Mem_Free(pixels);
5602                 pixels = NULL;
5603         }
5604
5605         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5606         {
5607                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), NULL);
5608                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
5609                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true);
5610                 Mem_Free(pixels);
5611                 pixels = NULL;
5612         }
5613
5614         if (basepixels)
5615                 Mem_Free(basepixels);
5616
5617         return skinframe;
5618 }
5619
5620 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
5621 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
5622 {
5623         int i;
5624         unsigned char *temp1, *temp2;
5625         skinframe_t *skinframe;
5626
5627         if (cls.state == ca_dedicated)
5628                 return NULL;
5629
5630         // if already loaded just return it, otherwise make a new skinframe
5631         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
5632         if (skinframe && skinframe->base)
5633                 return skinframe;
5634
5635         skinframe->stain = NULL;
5636         skinframe->merged = NULL;
5637         skinframe->base = NULL;
5638         skinframe->pants = NULL;
5639         skinframe->shirt = NULL;
5640         skinframe->nmap = NULL;
5641         skinframe->gloss = NULL;
5642         skinframe->glow = NULL;
5643         skinframe->fog = NULL;
5644         skinframe->reflect = NULL;
5645         skinframe->hasalpha = false;
5646
5647         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5648         if (!skindata)
5649                 return NULL;
5650
5651         if (developer_loading.integer)
5652                 Con_Printf("loading 32bit skin \"%s\"\n", name);
5653
5654         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
5655         {
5656                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5657                 temp2 = temp1 + width * height * 4;
5658                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5659                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5660                 Mem_Free(temp1);
5661         }
5662         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5663         if (textureflags & TEXF_ALPHA)
5664         {
5665                 for (i = 3;i < width * height * 4;i += 4)
5666                 {
5667                         if (skindata[i] < 255)
5668                         {
5669                                 skinframe->hasalpha = true;
5670                                 break;
5671                         }
5672                 }
5673                 if (r_loadfog && skinframe->hasalpha)
5674                 {
5675                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
5676                         memcpy(fogpixels, skindata, width * height * 4);
5677                         for (i = 0;i < width * height * 4;i += 4)
5678                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
5679                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5680                         Mem_Free(fogpixels);
5681                 }
5682         }
5683
5684         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
5685         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
5686
5687         return skinframe;
5688 }
5689
5690 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
5691 {
5692         int i;
5693         int featuresmask;
5694         skinframe_t *skinframe;
5695
5696         if (cls.state == ca_dedicated)
5697                 return NULL;
5698
5699         // if already loaded just return it, otherwise make a new skinframe
5700         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5701         if (skinframe && skinframe->base)
5702                 return skinframe;
5703
5704         skinframe->stain = NULL;
5705         skinframe->merged = NULL;
5706         skinframe->base = NULL;
5707         skinframe->pants = NULL;
5708         skinframe->shirt = NULL;
5709         skinframe->nmap = NULL;
5710         skinframe->gloss = NULL;
5711         skinframe->glow = NULL;
5712         skinframe->fog = NULL;
5713         skinframe->reflect = NULL;
5714         skinframe->hasalpha = false;
5715
5716         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5717         if (!skindata)
5718                 return NULL;
5719
5720         if (developer_loading.integer)
5721                 Con_Printf("loading quake skin \"%s\"\n", name);
5722
5723         // we actually don't upload anything until the first use, because mdl skins frequently go unused, and are almost never used in both modes (colormapped and non-colormapped)
5724         skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
5725         memcpy(skinframe->qpixels, skindata, width*height);
5726         skinframe->qwidth = width;
5727         skinframe->qheight = height;
5728
5729         featuresmask = 0;
5730         for (i = 0;i < width * height;i++)
5731                 featuresmask |= palette_featureflags[skindata[i]];
5732
5733         skinframe->hasalpha = false;
5734         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
5735         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
5736         skinframe->qgeneratemerged = true;
5737         skinframe->qgeneratebase = skinframe->qhascolormapping;
5738         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
5739
5740         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
5741         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
5742
5743         return skinframe;
5744 }
5745
5746 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
5747 {
5748         int width;
5749         int height;
5750         unsigned char *skindata;
5751
5752         if (!skinframe->qpixels)
5753                 return;
5754
5755         if (!skinframe->qhascolormapping)
5756                 colormapped = false;
5757
5758         if (colormapped)
5759         {
5760                 if (!skinframe->qgeneratebase)
5761                         return;
5762         }
5763         else
5764         {
5765                 if (!skinframe->qgeneratemerged)
5766                         return;
5767         }
5768
5769         width = skinframe->qwidth;
5770         height = skinframe->qheight;
5771         skindata = skinframe->qpixels;
5772
5773         if (skinframe->qgeneratenmap)
5774         {
5775                 unsigned char *temp1, *temp2;
5776                 skinframe->qgeneratenmap = false;
5777                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5778                 temp2 = temp1 + width * height * 4;
5779                 // use either a custom palette or the quake palette
5780                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
5781                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5782                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5783                 Mem_Free(temp1);
5784         }
5785
5786         if (skinframe->qgenerateglow)
5787         {
5788                 skinframe->qgenerateglow = false;
5789                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
5790         }
5791
5792         if (colormapped)
5793         {
5794                 skinframe->qgeneratebase = false;
5795                 skinframe->base  = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
5796                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
5797                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
5798         }
5799         else
5800         {
5801                 skinframe->qgeneratemerged = false;
5802                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
5803         }
5804
5805         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
5806         {
5807                 Mem_Free(skinframe->qpixels);
5808                 skinframe->qpixels = NULL;
5809         }
5810 }
5811
5812 skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, const unsigned char *skindata, int width, int height, const unsigned int *palette, const unsigned int *alphapalette)
5813 {
5814         int i;
5815         skinframe_t *skinframe;
5816
5817         if (cls.state == ca_dedicated)
5818                 return NULL;
5819
5820         // if already loaded just return it, otherwise make a new skinframe
5821         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5822         if (skinframe && skinframe->base)
5823                 return skinframe;
5824
5825         skinframe->stain = NULL;
5826         skinframe->merged = NULL;
5827         skinframe->base = NULL;
5828         skinframe->pants = NULL;
5829         skinframe->shirt = NULL;
5830         skinframe->nmap = NULL;
5831         skinframe->gloss = NULL;
5832         skinframe->glow = NULL;
5833         skinframe->fog = NULL;
5834         skinframe->reflect = NULL;
5835         skinframe->hasalpha = false;
5836
5837         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5838         if (!skindata)
5839                 return NULL;
5840
5841         if (developer_loading.integer)
5842                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
5843
5844         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
5845         if (textureflags & TEXF_ALPHA)
5846         {
5847                 for (i = 0;i < width * height;i++)
5848                 {
5849                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
5850                         {
5851                                 skinframe->hasalpha = true;
5852                                 break;
5853                         }
5854                 }
5855                 if (r_loadfog && skinframe->hasalpha)
5856                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
5857         }
5858
5859         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
5860         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
5861
5862         return skinframe;
5863 }
5864
5865 skinframe_t *R_SkinFrame_LoadMissing(void)
5866 {
5867         skinframe_t *skinframe;
5868
5869         if (cls.state == ca_dedicated)
5870                 return NULL;
5871
5872         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
5873         skinframe->stain = NULL;
5874         skinframe->merged = NULL;
5875         skinframe->base = NULL;
5876         skinframe->pants = NULL;
5877         skinframe->shirt = NULL;
5878         skinframe->nmap = NULL;
5879         skinframe->gloss = NULL;
5880         skinframe->glow = NULL;
5881         skinframe->fog = NULL;
5882         skinframe->reflect = NULL;
5883         skinframe->hasalpha = false;
5884
5885         skinframe->avgcolor[0] = rand() / RAND_MAX;
5886         skinframe->avgcolor[1] = rand() / RAND_MAX;
5887         skinframe->avgcolor[2] = rand() / RAND_MAX;
5888         skinframe->avgcolor[3] = 1;
5889
5890         return skinframe;
5891 }
5892
5893 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
5894 typedef struct suffixinfo_s
5895 {
5896         char *suffix;
5897         qboolean flipx, flipy, flipdiagonal;
5898 }
5899 suffixinfo_t;
5900 static suffixinfo_t suffix[3][6] =
5901 {
5902         {
5903                 {"px",   false, false, false},
5904                 {"nx",   false, false, false},
5905                 {"py",   false, false, false},
5906                 {"ny",   false, false, false},
5907                 {"pz",   false, false, false},
5908                 {"nz",   false, false, false}
5909         },
5910         {
5911                 {"posx", false, false, false},
5912                 {"negx", false, false, false},
5913                 {"posy", false, false, false},
5914                 {"negy", false, false, false},
5915                 {"posz", false, false, false},
5916                 {"negz", false, false, false}
5917         },
5918         {
5919                 {"rt",    true, false,  true},
5920                 {"lf",   false,  true,  true},
5921                 {"ft",    true,  true, false},
5922                 {"bk",   false, false, false},
5923                 {"up",    true, false,  true},
5924                 {"dn",    true, false,  true}
5925         }
5926 };
5927
5928 static int componentorder[4] = {0, 1, 2, 3};
5929
5930 rtexture_t *R_LoadCubemap(const char *basename)
5931 {
5932         int i, j, cubemapsize;
5933         unsigned char *cubemappixels, *image_buffer;
5934         rtexture_t *cubemaptexture;
5935         char name[256];
5936         // must start 0 so the first loadimagepixels has no requested width/height
5937         cubemapsize = 0;
5938         cubemappixels = NULL;
5939         cubemaptexture = NULL;
5940         // keep trying different suffix groups (posx, px, rt) until one loads
5941         for (j = 0;j < 3 && !cubemappixels;j++)
5942         {
5943                 // load the 6 images in the suffix group
5944                 for (i = 0;i < 6;i++)
5945                 {
5946                         // generate an image name based on the base and and suffix
5947                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
5948                         // load it
5949                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer)))
5950                         {
5951                                 // an image loaded, make sure width and height are equal
5952                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
5953                                 {
5954                                         // if this is the first image to load successfully, allocate the cubemap memory
5955                                         if (!cubemappixels && image_width >= 1)
5956                                         {
5957                                                 cubemapsize = image_width;
5958                                                 // note this clears to black, so unavailable sides are black
5959                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
5960                                         }
5961                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
5962                                         if (cubemappixels)
5963                                                 Image_CopyMux(cubemappixels+i*cubemapsize*cubemapsize*4, image_buffer, cubemapsize, cubemapsize, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, componentorder);
5964                                 }
5965                                 else
5966                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
5967                                 // free the image
5968                                 Mem_Free(image_buffer);
5969                         }
5970                 }
5971         }
5972         // if a cubemap loaded, upload it
5973         if (cubemappixels)
5974         {
5975                 if (developer_loading.integer)
5976                         Con_Printf("loading cubemap \"%s\"\n", basename);
5977
5978                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR, NULL);
5979                 Mem_Free(cubemappixels);
5980         }
5981         else
5982         {
5983                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
5984                 if (developer_loading.integer)
5985                 {
5986                         Con_Printf("(tried tried images ");
5987                         for (j = 0;j < 3;j++)
5988                                 for (i = 0;i < 6;i++)
5989                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
5990                         Con_Print(" and was unable to find any of them).\n");
5991                 }
5992         }
5993         return cubemaptexture;
5994 }
5995
5996 rtexture_t *R_GetCubemap(const char *basename)
5997 {
5998         int i;
5999         for (i = 0;i < r_texture_numcubemaps;i++)
6000                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6001                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6002         if (i >= MAX_CUBEMAPS)
6003                 return r_texture_whitecube;
6004         r_texture_numcubemaps++;
6005         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6006         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6007         return r_texture_cubemaps[i].texture;
6008 }
6009
6010 void R_FreeCubemaps(void)
6011 {
6012         int i;
6013         for (i = 0;i < r_texture_numcubemaps;i++)
6014         {
6015                 if (developer_loading.integer)
6016                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6017                 if (r_texture_cubemaps[i].texture)
6018                         R_FreeTexture(r_texture_cubemaps[i].texture);
6019         }
6020         r_texture_numcubemaps = 0;
6021 }
6022
6023 void R_Main_FreeViewCache(void)
6024 {
6025         if (r_refdef.viewcache.entityvisible)
6026                 Mem_Free(r_refdef.viewcache.entityvisible);
6027         if (r_refdef.viewcache.world_pvsbits)
6028                 Mem_Free(r_refdef.viewcache.world_pvsbits);
6029         if (r_refdef.viewcache.world_leafvisible)
6030                 Mem_Free(r_refdef.viewcache.world_leafvisible);
6031         if (r_refdef.viewcache.world_surfacevisible)
6032                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6033         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6034 }
6035
6036 void R_Main_ResizeViewCache(void)
6037 {
6038         int numentities = r_refdef.scene.numentities;
6039         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6040         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6041         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6042         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6043         if (r_refdef.viewcache.maxentities < numentities)
6044         {
6045                 r_refdef.viewcache.maxentities = numentities;
6046                 if (r_refdef.viewcache.entityvisible)
6047                         Mem_Free(r_refdef.viewcache.entityvisible);
6048                 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6049         }
6050         if (r_refdef.viewcache.world_numclusters != numclusters)
6051         {
6052                 r_refdef.viewcache.world_numclusters = numclusters;
6053                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6054                 if (r_refdef.viewcache.world_pvsbits)
6055                         Mem_Free(r_refdef.viewcache.world_pvsbits);
6056                 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6057         }
6058         if (r_refdef.viewcache.world_numleafs != numleafs)
6059         {
6060                 r_refdef.viewcache.world_numleafs = numleafs;
6061                 if (r_refdef.viewcache.world_leafvisible)
6062                         Mem_Free(r_refdef.viewcache.world_leafvisible);
6063                 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6064         }
6065         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6066         {
6067                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6068                 if (r_refdef.viewcache.world_surfacevisible)
6069                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
6070                 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6071         }
6072 }
6073
6074 extern rtexture_t *loadingscreentexture;
6075 void gl_main_start(void)
6076 {
6077         loadingscreentexture = NULL;
6078         r_texture_blanknormalmap = NULL;
6079         r_texture_white = NULL;
6080         r_texture_grey128 = NULL;
6081         r_texture_black = NULL;
6082         r_texture_whitecube = NULL;
6083         r_texture_normalizationcube = NULL;
6084         r_texture_fogattenuation = NULL;
6085         r_texture_gammaramps = NULL;
6086         r_texture_numcubemaps = 0;
6087
6088         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
6089         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6090
6091         switch(vid.renderpath)
6092         {
6093         case RENDERPATH_GL20:
6094         case RENDERPATH_CGGL:
6095                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6096                 Cvar_SetValueQuick(&gl_combine, 1);
6097                 Cvar_SetValueQuick(&r_glsl, 1);
6098                 r_loadnormalmap = true;
6099                 r_loadgloss = true;
6100                 r_loadfog = false;
6101                 break;
6102         case RENDERPATH_GL13:
6103                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6104                 Cvar_SetValueQuick(&gl_combine, 1);
6105                 Cvar_SetValueQuick(&r_glsl, 0);
6106                 r_loadnormalmap = false;
6107                 r_loadgloss = false;
6108                 r_loadfog = true;
6109                 break;
6110         case RENDERPATH_GL11:
6111                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6112                 Cvar_SetValueQuick(&gl_combine, 0);
6113                 Cvar_SetValueQuick(&r_glsl, 0);
6114                 r_loadnormalmap = false;
6115                 r_loadgloss = false;
6116                 r_loadfog = true;
6117                 break;
6118         }
6119
6120         R_AnimCache_Free();
6121         R_FrameData_Reset();
6122
6123         r_numqueries = 0;
6124         r_maxqueries = 0;
6125         memset(r_queries, 0, sizeof(r_queries));
6126
6127         r_qwskincache = NULL;
6128         r_qwskincache_size = 0;
6129
6130         // set up r_skinframe loading system for textures
6131         memset(&r_skinframe, 0, sizeof(r_skinframe));
6132         r_skinframe.loadsequence = 1;
6133         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
6134
6135         r_main_texturepool = R_AllocTexturePool();
6136         R_BuildBlankTextures();
6137         R_BuildNoTexture();
6138         if (vid.support.arb_texture_cube_map)
6139         {
6140                 R_BuildWhiteCube();
6141                 R_BuildNormalizationCube();
6142         }
6143         r_texture_fogattenuation = NULL;
6144         r_texture_gammaramps = NULL;
6145         //r_texture_fogintensity = NULL;
6146         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6147         memset(&r_waterstate, 0, sizeof(r_waterstate));
6148         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6149         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
6150         glslshaderstring = NULL;
6151 #ifdef SUPPORTCG
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_Restart_f();
6200 }
6201
6202 extern void CL_ParseEntityLump(char *entitystring);
6203 void gl_main_newmap(void)
6204 {
6205         // FIXME: move this code to client
6206         int l;
6207         char *entities, entname[MAX_QPATH];
6208         if (r_qwskincache)
6209                 Mem_Free(r_qwskincache);
6210         r_qwskincache = NULL;
6211         r_qwskincache_size = 0;
6212         if (cl.worldmodel)
6213         {
6214                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
6215                 l = (int)strlen(entname) - 4;
6216                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
6217                 {
6218                         memcpy(entname + l, ".ent", 5);
6219                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
6220                         {
6221                                 CL_ParseEntityLump(entities);
6222                                 Mem_Free(entities);
6223                                 return;
6224                         }
6225                 }
6226                 if (cl.worldmodel->brush.entities)
6227                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
6228         }
6229         R_Main_FreeViewCache();
6230
6231         R_FrameData_Reset();
6232 }
6233
6234 void GL_Main_Init(void)
6235 {
6236         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
6237
6238         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
6239         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
6240         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
6241         if (gamemode == GAME_NEHAHRA)
6242         {
6243                 Cvar_RegisterVariable (&gl_fogenable);
6244                 Cvar_RegisterVariable (&gl_fogdensity);
6245                 Cvar_RegisterVariable (&gl_fogred);
6246                 Cvar_RegisterVariable (&gl_foggreen);
6247                 Cvar_RegisterVariable (&gl_fogblue);
6248                 Cvar_RegisterVariable (&gl_fogstart);
6249                 Cvar_RegisterVariable (&gl_fogend);
6250                 Cvar_RegisterVariable (&gl_skyclip);
6251         }
6252         Cvar_RegisterVariable(&r_motionblur);
6253         Cvar_RegisterVariable(&r_motionblur_maxblur);
6254         Cvar_RegisterVariable(&r_motionblur_bmin);
6255         Cvar_RegisterVariable(&r_motionblur_vmin);
6256         Cvar_RegisterVariable(&r_motionblur_vmax);
6257         Cvar_RegisterVariable(&r_motionblur_vcoeff);
6258         Cvar_RegisterVariable(&r_motionblur_randomize);
6259         Cvar_RegisterVariable(&r_damageblur);
6260         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
6261         Cvar_RegisterVariable(&r_equalize_entities_minambient);
6262         Cvar_RegisterVariable(&r_equalize_entities_by);
6263         Cvar_RegisterVariable(&r_equalize_entities_to);
6264         Cvar_RegisterVariable(&r_depthfirst);
6265         Cvar_RegisterVariable(&r_useinfinitefarclip);
6266         Cvar_RegisterVariable(&r_farclip_base);
6267         Cvar_RegisterVariable(&r_farclip_world);
6268         Cvar_RegisterVariable(&r_nearclip);
6269         Cvar_RegisterVariable(&r_showbboxes);
6270         Cvar_RegisterVariable(&r_showsurfaces);
6271         Cvar_RegisterVariable(&r_showtris);
6272         Cvar_RegisterVariable(&r_shownormals);
6273         Cvar_RegisterVariable(&r_showlighting);
6274         Cvar_RegisterVariable(&r_showshadowvolumes);
6275         Cvar_RegisterVariable(&r_showcollisionbrushes);
6276         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
6277         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
6278         Cvar_RegisterVariable(&r_showdisabledepthtest);
6279         Cvar_RegisterVariable(&r_drawportals);
6280         Cvar_RegisterVariable(&r_drawentities);
6281         Cvar_RegisterVariable(&r_cullentities_trace);
6282         Cvar_RegisterVariable(&r_cullentities_trace_samples);
6283         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
6284         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
6285         Cvar_RegisterVariable(&r_cullentities_trace_delay);
6286         Cvar_RegisterVariable(&r_drawviewmodel);
6287         Cvar_RegisterVariable(&r_speeds);
6288         Cvar_RegisterVariable(&r_fullbrights);
6289         Cvar_RegisterVariable(&r_wateralpha);
6290         Cvar_RegisterVariable(&r_dynamic);
6291         Cvar_RegisterVariable(&r_fullbright);
6292         Cvar_RegisterVariable(&r_shadows);
6293         Cvar_RegisterVariable(&r_shadows_darken);
6294         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
6295         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
6296         Cvar_RegisterVariable(&r_shadows_throwdistance);
6297         Cvar_RegisterVariable(&r_shadows_throwdirection);
6298         Cvar_RegisterVariable(&r_shadows_focus);
6299         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
6300         Cvar_RegisterVariable(&r_q1bsp_skymasking);
6301         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
6302         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
6303         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
6304         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
6305         Cvar_RegisterVariable(&r_fog_exp2);
6306         Cvar_RegisterVariable(&r_drawfog);
6307         Cvar_RegisterVariable(&r_transparentdepthmasking);
6308         Cvar_RegisterVariable(&r_texture_dds_load);
6309         Cvar_RegisterVariable(&r_texture_dds_save);
6310         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
6311         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
6312         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
6313         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
6314         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
6315         Cvar_RegisterVariable(&r_textureunits);
6316         Cvar_RegisterVariable(&gl_combine);
6317         Cvar_RegisterVariable(&r_glsl);
6318         Cvar_RegisterVariable(&r_glsl_deluxemapping);
6319         Cvar_RegisterVariable(&r_glsl_offsetmapping);
6320         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
6321         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
6322         Cvar_RegisterVariable(&r_glsl_postprocess);
6323         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
6324         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
6325         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
6326         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
6327         Cvar_RegisterVariable(&r_water);
6328         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
6329         Cvar_RegisterVariable(&r_water_clippingplanebias);
6330         Cvar_RegisterVariable(&r_water_refractdistort);
6331         Cvar_RegisterVariable(&r_water_reflectdistort);
6332         Cvar_RegisterVariable(&r_lerpsprites);
6333         Cvar_RegisterVariable(&r_lerpmodels);
6334         Cvar_RegisterVariable(&r_lerplightstyles);
6335         Cvar_RegisterVariable(&r_waterscroll);
6336         Cvar_RegisterVariable(&r_bloom);
6337         Cvar_RegisterVariable(&r_bloom_colorscale);
6338         Cvar_RegisterVariable(&r_bloom_brighten);
6339         Cvar_RegisterVariable(&r_bloom_blur);
6340         Cvar_RegisterVariable(&r_bloom_resolution);
6341         Cvar_RegisterVariable(&r_bloom_colorexponent);
6342         Cvar_RegisterVariable(&r_bloom_colorsubtract);
6343         Cvar_RegisterVariable(&r_hdr);
6344         Cvar_RegisterVariable(&r_hdr_scenebrightness);
6345         Cvar_RegisterVariable(&r_hdr_glowintensity);
6346         Cvar_RegisterVariable(&r_hdr_range);
6347         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
6348         Cvar_RegisterVariable(&developer_texturelogging);
6349         Cvar_RegisterVariable(&gl_lightmaps);
6350         Cvar_RegisterVariable(&r_test);
6351         Cvar_RegisterVariable(&r_batchmode);
6352         Cvar_RegisterVariable(&r_glsl_saturation);
6353         Cvar_RegisterVariable(&r_framedatasize);
6354         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
6355                 Cvar_SetValue("r_fullbrights", 0);
6356         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
6357
6358         Cvar_RegisterVariable(&r_track_sprites);
6359         Cvar_RegisterVariable(&r_track_sprites_flags);
6360         Cvar_RegisterVariable(&r_track_sprites_scalew);
6361         Cvar_RegisterVariable(&r_track_sprites_scaleh);
6362         Cvar_RegisterVariable(&r_overheadsprites_perspective);
6363         Cvar_RegisterVariable(&r_overheadsprites_pushback);
6364 }
6365
6366 extern void R_Textures_Init(void);
6367 extern void GL_Draw_Init(void);
6368 extern void GL_Main_Init(void);
6369 extern void R_Shadow_Init(void);
6370 extern void R_Sky_Init(void);
6371 extern void GL_Surf_Init(void);
6372 extern void R_Particles_Init(void);
6373 extern void R_Explosion_Init(void);
6374 extern void gl_backend_init(void);
6375 extern void Sbar_Init(void);
6376 extern void R_LightningBeams_Init(void);
6377 extern void Mod_RenderInit(void);
6378 extern void Font_Init(void);
6379
6380 void Render_Init(void)
6381 {
6382         gl_backend_init();
6383         R_Textures_Init();
6384         GL_Main_Init();
6385         Font_Init();
6386         GL_Draw_Init();
6387         R_Shadow_Init();
6388         R_Sky_Init();
6389         GL_Surf_Init();
6390         Sbar_Init();
6391         R_Particles_Init();
6392         R_Explosion_Init();
6393         R_LightningBeams_Init();
6394         Mod_RenderInit();
6395 }
6396
6397 /*
6398 ===============
6399 GL_Init
6400 ===============
6401 */
6402 extern char *ENGINE_EXTENSIONS;
6403 void GL_Init (void)
6404 {
6405         gl_renderer = (const char *)qglGetString(GL_RENDERER);
6406         gl_vendor = (const char *)qglGetString(GL_VENDOR);
6407         gl_version = (const char *)qglGetString(GL_VERSION);
6408         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
6409
6410         if (!gl_extensions)
6411                 gl_extensions = "";
6412         if (!gl_platformextensions)
6413                 gl_platformextensions = "";
6414
6415         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
6416         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
6417         Con_Printf("GL_VERSION: %s\n", gl_version);
6418         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
6419         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
6420
6421         VID_CheckExtensions();
6422
6423         // LordHavoc: report supported extensions
6424         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
6425
6426         // clear to black (loading plaque will be seen over this)
6427         CHECKGLERROR
6428         qglClearColor(0,0,0,1);CHECKGLERROR
6429         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
6430 }
6431
6432 int R_CullBox(const vec3_t mins, const vec3_t maxs)
6433 {
6434         int i;
6435         mplane_t *p;
6436         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6437         {
6438                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
6439                 if (i == 4)
6440                         continue;
6441                 p = r_refdef.view.frustum + i;
6442                 switch(p->signbits)
6443                 {
6444                 default:
6445                 case 0:
6446                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6447                                 return true;
6448                         break;
6449                 case 1:
6450                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6451                                 return true;
6452                         break;
6453                 case 2:
6454                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6455                                 return true;
6456                         break;
6457                 case 3:
6458                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6459                                 return true;
6460                         break;
6461                 case 4:
6462                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6463                                 return true;
6464                         break;
6465                 case 5:
6466                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6467                                 return true;
6468                         break;
6469                 case 6:
6470                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6471                                 return true;
6472                         break;
6473                 case 7:
6474                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6475                                 return true;
6476                         break;
6477                 }
6478         }
6479         return false;
6480 }
6481
6482 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
6483 {
6484         int i;
6485         const mplane_t *p;
6486         for (i = 0;i < numplanes;i++)
6487         {
6488                 p = planes + i;
6489                 switch(p->signbits)
6490                 {
6491                 default:
6492                 case 0:
6493                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6494                                 return true;
6495                         break;
6496                 case 1:
6497                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6498                                 return true;
6499                         break;
6500                 case 2:
6501                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6502                                 return true;
6503                         break;
6504                 case 3:
6505                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6506                                 return true;
6507                         break;
6508                 case 4:
6509                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6510                                 return true;
6511                         break;
6512                 case 5:
6513                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6514                                 return true;
6515                         break;
6516                 case 6:
6517                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6518                                 return true;
6519                         break;
6520                 case 7:
6521                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6522                                 return true;
6523                         break;
6524                 }
6525         }
6526         return false;
6527 }
6528
6529 //==================================================================================
6530
6531 // LordHavoc: this stores temporary data used within the same frame
6532
6533 qboolean r_framedata_failed;
6534 static size_t r_framedata_size;
6535 static size_t r_framedata_current;
6536 static void *r_framedata_base;
6537
6538 void R_FrameData_Reset(void)
6539 {
6540         if (r_framedata_base)
6541                 Mem_Free(r_framedata_base);
6542         r_framedata_base = NULL;
6543         r_framedata_size = 0;
6544         r_framedata_current = 0;
6545         r_framedata_failed = false;
6546 }
6547
6548 void R_FrameData_NewFrame(void)
6549 {
6550         size_t wantedsize;
6551         if (r_framedata_failed)
6552                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
6553         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
6554         wantedsize = bound(65536, wantedsize, 128*1024*1024);
6555         if (r_framedata_size != wantedsize)
6556         {
6557                 r_framedata_size = wantedsize;
6558                 if (r_framedata_base)
6559                         Mem_Free(r_framedata_base);
6560                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
6561         }
6562         r_framedata_current = 0;
6563         r_framedata_failed = false;
6564 }
6565
6566 void *R_FrameData_Alloc(size_t size)
6567 {
6568         void *data;
6569
6570         // align to 16 byte boundary
6571         size = (size + 15) & ~15;
6572         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
6573         r_framedata_current += size;
6574
6575         // check overflow
6576         if (r_framedata_current > r_framedata_size)
6577                 r_framedata_failed = true;
6578
6579         // return NULL on everything after a failure
6580         if (r_framedata_failed)
6581                 return NULL;
6582
6583         return data;
6584 }
6585
6586 void *R_FrameData_Store(size_t size, void *data)
6587 {
6588         void *d = R_FrameData_Alloc(size);
6589         if (d)
6590                 memcpy(d, data, size);
6591         return d;
6592 }
6593
6594 //==================================================================================
6595
6596 // LordHavoc: animcache originally written by Echon, rewritten since then
6597
6598 /**
6599  * Animation cache prevents re-generating mesh data for an animated model
6600  * multiple times in one frame for lighting, shadowing, reflections, etc.
6601  */
6602
6603 void R_AnimCache_Free(void)
6604 {
6605 }
6606
6607 void R_AnimCache_ClearCache(void)
6608 {
6609         int i;
6610         entity_render_t *ent;
6611
6612         for (i = 0;i < r_refdef.scene.numentities;i++)
6613         {
6614                 ent = r_refdef.scene.entities[i];
6615                 ent->animcache_vertex3f = NULL;
6616                 ent->animcache_normal3f = NULL;
6617                 ent->animcache_svector3f = NULL;
6618                 ent->animcache_tvector3f = NULL;
6619         }
6620 }
6621
6622 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6623 {
6624         dp_model_t *model = ent->model;
6625         int numvertices;
6626         // see if it's already cached this frame
6627         if (ent->animcache_vertex3f)
6628         {
6629                 // add normals/tangents if needed
6630                 if (wantnormals || wanttangents)
6631                 {
6632                         if (ent->animcache_normal3f)
6633                                 wantnormals = false;
6634                         if (ent->animcache_svector3f)
6635                                 wanttangents = false;
6636                         if (wantnormals || wanttangents)
6637                         {
6638                                 numvertices = model->surfmesh.num_vertices;
6639                                 if (wantnormals)
6640                                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6641                                 if (wanttangents)
6642                                 {
6643                                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6644                                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6645                                 }
6646                                 if (!r_framedata_failed)
6647                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
6648                         }
6649                 }
6650         }
6651         else
6652         {
6653                 // see if this ent is worth caching
6654                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
6655                         return false;
6656                 // get some memory for this entity and generate mesh data
6657                 numvertices = model->surfmesh.num_vertices;
6658                 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6659                 if (wantnormals)
6660                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6661                 if (wanttangents)
6662                 {
6663                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6664                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6665                 }
6666                 if (!r_framedata_failed)
6667                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
6668         }
6669         return !r_framedata_failed;
6670 }
6671
6672 void R_AnimCache_CacheVisibleEntities(void)
6673 {
6674         int i;
6675         qboolean wantnormals = !r_showsurfaces.integer;
6676         qboolean wanttangents = !r_showsurfaces.integer;
6677
6678         switch(vid.renderpath)
6679         {
6680         case RENDERPATH_GL20:
6681         case RENDERPATH_CGGL:
6682                 break;
6683         case RENDERPATH_GL13:
6684         case RENDERPATH_GL11:
6685                 wanttangents = false;
6686                 break;
6687         }
6688
6689         // TODO: thread this
6690         // NOTE: R_PrepareRTLights() also caches entities
6691
6692         for (i = 0;i < r_refdef.scene.numentities;i++)
6693                 if (r_refdef.viewcache.entityvisible[i])
6694                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
6695 }
6696
6697 //==================================================================================
6698
6699 static void R_View_UpdateEntityLighting (void)
6700 {
6701         int i;
6702         entity_render_t *ent;
6703         vec3_t tempdiffusenormal, avg;
6704         vec_t f, fa, fd, fdd;
6705         qboolean skipunseen = r_shadows.integer != 1 || R_Shadow_ShadowMappingEnabled();
6706
6707         for (i = 0;i < r_refdef.scene.numentities;i++)
6708         {
6709                 ent = r_refdef.scene.entities[i];
6710
6711                 // skip unseen models
6712                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
6713                         continue;
6714
6715                 // skip bsp models
6716                 if (ent->model && ent->model->brush.num_leafs)
6717                 {
6718                         // TODO: use modellight for r_ambient settings on world?
6719                         VectorSet(ent->modellight_ambient, 0, 0, 0);
6720                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
6721                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
6722                         continue;
6723                 }
6724
6725                 // fetch the lighting from the worldmodel data
6726                 VectorClear(ent->modellight_ambient);
6727                 VectorClear(ent->modellight_diffuse);
6728                 VectorClear(tempdiffusenormal);
6729                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
6730                 {
6731                         vec3_t org;
6732                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6733                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
6734                         if(ent->flags & RENDER_EQUALIZE)
6735                         {
6736                                 // first fix up ambient lighting...
6737                                 if(r_equalize_entities_minambient.value > 0)
6738                                 {
6739                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
6740                                         if(fd > 0)
6741                                         {
6742                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
6743                                                 if(fa < r_equalize_entities_minambient.value * fd)
6744                                                 {
6745                                                         // solve:
6746                                                         //   fa'/fd' = minambient
6747                                                         //   fa'+0.25*fd' = fa+0.25*fd
6748                                                         //   ...
6749                                                         //   fa' = fd' * minambient
6750                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
6751                                                         //   ...
6752                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
6753                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
6754                                                         //   ...
6755                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
6756                                                         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
6757                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
6758                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6759                                                 }
6760                                         }
6761                                 }
6762
6763                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
6764                                 {
6765                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
6766                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
6767                                         if(f > 0)
6768                                         {
6769                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
6770                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
6771                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6772                                         }
6773                                 }
6774                         }
6775                 }
6776                 else // highly rare
6777                         VectorSet(ent->modellight_ambient, 1, 1, 1);
6778
6779                 // move the light direction into modelspace coordinates for lighting code
6780                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
6781                 if(VectorLength2(ent->modellight_lightdir) == 0)
6782                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
6783                 VectorNormalize(ent->modellight_lightdir);
6784         }
6785 }
6786
6787 #define MAX_LINEOFSIGHTTRACES 64
6788
6789 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
6790 {
6791         int i;
6792         vec3_t boxmins, boxmaxs;
6793         vec3_t start;
6794         vec3_t end;
6795         dp_model_t *model = r_refdef.scene.worldmodel;
6796
6797         if (!model || !model->brush.TraceLineOfSight)
6798                 return true;
6799
6800         // expand the box a little
6801         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
6802         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
6803         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
6804         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
6805         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
6806         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
6807
6808         // return true if eye is inside enlarged box
6809         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
6810                 return true;
6811
6812         // try center
6813         VectorCopy(eye, start);
6814         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
6815         if (model->brush.TraceLineOfSight(model, start, end))
6816                 return true;
6817
6818         // try various random positions
6819         for (i = 0;i < numsamples;i++)
6820         {
6821                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
6822                 if (model->brush.TraceLineOfSight(model, start, end))
6823                         return true;
6824         }
6825
6826         return false;
6827 }
6828
6829
6830 static void R_View_UpdateEntityVisible (void)
6831 {
6832         int i;
6833         int renderimask;
6834         int samples;
6835         entity_render_t *ent;
6836
6837         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
6838                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
6839                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
6840                 :                                                          RENDER_EXTERIORMODEL;
6841         if (!r_drawviewmodel.integer)
6842                 renderimask |= RENDER_VIEWMODEL;
6843         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
6844         {
6845                 // worldmodel can check visibility
6846                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
6847                 for (i = 0;i < r_refdef.scene.numentities;i++)
6848                 {
6849                         ent = r_refdef.scene.entities[i];
6850                         if (!(ent->flags & renderimask))
6851                         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)))
6852                         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))
6853                                 r_refdef.viewcache.entityvisible[i] = true;
6854                 }
6855                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
6856                 {
6857                         for (i = 0;i < r_refdef.scene.numentities;i++)
6858                         {
6859                                 ent = r_refdef.scene.entities[i];
6860                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
6861                                 {
6862                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
6863                                         if (samples < 0)
6864                                                 continue; // temp entities do pvs only
6865                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
6866                                                 ent->last_trace_visibility = realtime;
6867                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
6868                                                 r_refdef.viewcache.entityvisible[i] = 0;
6869                                 }
6870                         }
6871                 }
6872         }
6873         else
6874         {
6875                 // no worldmodel or it can't check visibility
6876                 for (i = 0;i < r_refdef.scene.numentities;i++)
6877                 {
6878                         ent = r_refdef.scene.entities[i];
6879                         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));
6880                 }
6881         }
6882 }
6883
6884 /// only used if skyrendermasked, and normally returns false
6885 int R_DrawBrushModelsSky (void)
6886 {
6887         int i, sky;
6888         entity_render_t *ent;
6889
6890         sky = false;
6891         for (i = 0;i < r_refdef.scene.numentities;i++)
6892         {
6893                 if (!r_refdef.viewcache.entityvisible[i])
6894                         continue;
6895                 ent = r_refdef.scene.entities[i];
6896                 if (!ent->model || !ent->model->DrawSky)
6897                         continue;
6898                 ent->model->DrawSky(ent);
6899                 sky = true;
6900         }
6901         return sky;
6902 }
6903
6904 static void R_DrawNoModel(entity_render_t *ent);
6905 static void R_DrawModels(void)
6906 {
6907         int i;
6908         entity_render_t *ent;
6909
6910         for (i = 0;i < r_refdef.scene.numentities;i++)
6911         {
6912                 if (!r_refdef.viewcache.entityvisible[i])
6913                         continue;
6914                 ent = r_refdef.scene.entities[i];
6915                 r_refdef.stats.entities++;
6916                 if (ent->model && ent->model->Draw != NULL)
6917                         ent->model->Draw(ent);
6918                 else
6919                         R_DrawNoModel(ent);
6920         }
6921 }
6922
6923 static void R_DrawModelsDepth(void)
6924 {
6925         int i;
6926         entity_render_t *ent;
6927
6928         for (i = 0;i < r_refdef.scene.numentities;i++)
6929         {
6930                 if (!r_refdef.viewcache.entityvisible[i])
6931                         continue;
6932                 ent = r_refdef.scene.entities[i];
6933                 if (ent->model && ent->model->DrawDepth != NULL)
6934                         ent->model->DrawDepth(ent);
6935         }
6936 }
6937
6938 static void R_DrawModelsDebug(void)
6939 {
6940         int i;
6941         entity_render_t *ent;
6942
6943         for (i = 0;i < r_refdef.scene.numentities;i++)
6944         {
6945                 if (!r_refdef.viewcache.entityvisible[i])
6946                         continue;
6947                 ent = r_refdef.scene.entities[i];
6948                 if (ent->model && ent->model->DrawDebug != NULL)
6949                         ent->model->DrawDebug(ent);
6950         }
6951 }
6952
6953 static void R_DrawModelsAddWaterPlanes(void)
6954 {
6955         int i;
6956         entity_render_t *ent;
6957
6958         for (i = 0;i < r_refdef.scene.numentities;i++)
6959         {
6960                 if (!r_refdef.viewcache.entityvisible[i])
6961                         continue;
6962                 ent = r_refdef.scene.entities[i];
6963                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
6964                         ent->model->DrawAddWaterPlanes(ent);
6965         }
6966 }
6967
6968 static void R_View_SetFrustum(void)
6969 {
6970         int i;
6971         double slopex, slopey;
6972         vec3_t forward, left, up, origin;
6973
6974         // we can't trust r_refdef.view.forward and friends in reflected scenes
6975         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
6976
6977 #if 0
6978         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
6979         r_refdef.view.frustum[0].normal[1] = 0 - 0;
6980         r_refdef.view.frustum[0].normal[2] = -1 - 0;
6981         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
6982         r_refdef.view.frustum[1].normal[1] = 0 + 0;
6983         r_refdef.view.frustum[1].normal[2] = -1 + 0;
6984         r_refdef.view.frustum[2].normal[0] = 0 - 0;
6985         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
6986         r_refdef.view.frustum[2].normal[2] = -1 - 0;
6987         r_refdef.view.frustum[3].normal[0] = 0 + 0;
6988         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
6989         r_refdef.view.frustum[3].normal[2] = -1 + 0;
6990 #endif
6991
6992 #if 0
6993         zNear = r_refdef.nearclip;
6994         nudge = 1.0 - 1.0 / (1<<23);
6995         r_refdef.view.frustum[4].normal[0] = 0 - 0;
6996         r_refdef.view.frustum[4].normal[1] = 0 - 0;
6997         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
6998         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
6999         r_refdef.view.frustum[5].normal[0] = 0 + 0;
7000         r_refdef.view.frustum[5].normal[1] = 0 + 0;
7001         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
7002         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
7003 #endif
7004
7005
7006
7007 #if 0
7008         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
7009         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
7010         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
7011         r_refdef.view.frustum[0].dist = m[15] - m[12];
7012
7013         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
7014         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
7015         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
7016         r_refdef.view.frustum[1].dist = m[15] + m[12];
7017
7018         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
7019         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
7020         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
7021         r_refdef.view.frustum[2].dist = m[15] - m[13];
7022
7023         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
7024         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
7025         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
7026         r_refdef.view.frustum[3].dist = m[15] + m[13];
7027
7028         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
7029         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
7030         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
7031         r_refdef.view.frustum[4].dist = m[15] - m[14];
7032
7033         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
7034         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
7035         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
7036         r_refdef.view.frustum[5].dist = m[15] + m[14];
7037 #endif
7038
7039         if (r_refdef.view.useperspective)
7040         {
7041                 slopex = 1.0 / r_refdef.view.frustum_x;
7042                 slopey = 1.0 / r_refdef.view.frustum_y;
7043                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
7044                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
7045                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
7046                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
7047                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7048
7049                 // Leaving those out was a mistake, those were in the old code, and they
7050                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
7051                 // I couldn't reproduce it after adding those normalizations. --blub
7052                 VectorNormalize(r_refdef.view.frustum[0].normal);
7053                 VectorNormalize(r_refdef.view.frustum[1].normal);
7054                 VectorNormalize(r_refdef.view.frustum[2].normal);
7055                 VectorNormalize(r_refdef.view.frustum[3].normal);
7056
7057                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
7058                 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]);
7059                 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]);
7060                 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]);
7061                 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]);
7062
7063                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
7064                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
7065                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
7066                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
7067                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7068         }
7069         else
7070         {
7071                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
7072                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
7073                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
7074                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
7075                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7076                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
7077                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
7078                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
7079                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
7080                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7081         }
7082         r_refdef.view.numfrustumplanes = 5;
7083
7084         if (r_refdef.view.useclipplane)
7085         {
7086                 r_refdef.view.numfrustumplanes = 6;
7087                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
7088         }
7089
7090         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7091                 PlaneClassify(r_refdef.view.frustum + i);
7092
7093         // LordHavoc: note to all quake engine coders, Quake had a special case
7094         // for 90 degrees which assumed a square view (wrong), so I removed it,
7095         // Quake2 has it disabled as well.
7096
7097         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
7098         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
7099         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
7100         //PlaneClassify(&frustum[0]);
7101
7102         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
7103         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
7104         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
7105         //PlaneClassify(&frustum[1]);
7106
7107         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
7108         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
7109         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
7110         //PlaneClassify(&frustum[2]);
7111
7112         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
7113         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
7114         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
7115         //PlaneClassify(&frustum[3]);
7116
7117         // nearclip plane
7118         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
7119         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
7120         //PlaneClassify(&frustum[4]);
7121 }
7122
7123 void R_View_Update(void)
7124 {
7125         R_Main_ResizeViewCache();
7126         R_View_SetFrustum();
7127         R_View_WorldVisibility(r_refdef.view.useclipplane);
7128         R_View_UpdateEntityVisible();
7129         R_View_UpdateEntityLighting();
7130 }
7131
7132 void R_SetupView(qboolean allowwaterclippingplane)
7133 {
7134         const float *customclipplane = NULL;
7135         float plane[4];
7136         if (r_refdef.view.useclipplane && allowwaterclippingplane)
7137         {
7138                 // LordHavoc: couldn't figure out how to make this approach the
7139                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
7140                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
7141                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
7142                         dist = r_refdef.view.clipplane.dist;
7143                 plane[0] = r_refdef.view.clipplane.normal[0];
7144                 plane[1] = r_refdef.view.clipplane.normal[1];
7145                 plane[2] = r_refdef.view.clipplane.normal[2];
7146                 plane[3] = dist;
7147                 customclipplane = plane;
7148         }
7149
7150         if (!r_refdef.view.useperspective)
7151                 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);
7152         else if (vid.stencil && r_useinfinitefarclip.integer)
7153                 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);
7154         else
7155                 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);
7156         R_SetViewport(&r_refdef.view.viewport);
7157 }
7158
7159 void R_EntityMatrix(const matrix4x4_t *matrix)
7160 {
7161         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
7162         {
7163                 gl_modelmatrixchanged = false;
7164                 gl_modelmatrix = *matrix;
7165                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
7166                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
7167                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
7168                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
7169                 CHECKGLERROR
7170                 switch(vid.renderpath)
7171                 {
7172                 case RENDERPATH_GL20:
7173                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
7174                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
7175                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7176                         break;
7177                 case RENDERPATH_CGGL:
7178 #ifdef SUPPORTCG
7179                         CHECKCGERROR
7180                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
7181                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
7182                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7183 #endif
7184                         break;
7185                 case RENDERPATH_GL13:
7186                 case RENDERPATH_GL11:
7187                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7188                         break;
7189                 }
7190         }
7191 }
7192
7193 void R_ResetViewRendering2D(void)
7194 {
7195         r_viewport_t viewport;
7196         DrawQ_Finish();
7197
7198         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
7199         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);
7200         R_SetViewport(&viewport);
7201         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
7202         GL_Color(1, 1, 1, 1);
7203         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7204         GL_BlendFunc(GL_ONE, GL_ZERO);
7205         GL_AlphaTest(false);
7206         GL_ScissorTest(false);
7207         GL_DepthMask(false);
7208         GL_DepthRange(0, 1);
7209         GL_DepthTest(false);
7210         R_EntityMatrix(&identitymatrix);
7211         R_Mesh_ResetTextureState();
7212         GL_PolygonOffset(0, 0);
7213         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7214         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7215         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7216         qglStencilMask(~0);CHECKGLERROR
7217         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7218         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7219         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
7220 }
7221
7222 void R_ResetViewRendering3D(void)
7223 {
7224         DrawQ_Finish();
7225
7226         R_SetupView(true);
7227         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7228         GL_Color(1, 1, 1, 1);
7229         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7230         GL_BlendFunc(GL_ONE, GL_ZERO);
7231         GL_AlphaTest(false);
7232         GL_ScissorTest(true);
7233         GL_DepthMask(true);
7234         GL_DepthRange(0, 1);
7235         GL_DepthTest(true);
7236         R_EntityMatrix(&identitymatrix);
7237         R_Mesh_ResetTextureState();
7238         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7239         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7240         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7241         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7242         qglStencilMask(~0);CHECKGLERROR
7243         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7244         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7245         GL_CullFace(r_refdef.view.cullface_back);
7246 }
7247
7248 void R_RenderScene(void);
7249 void R_RenderWaterPlanes(void);
7250
7251 static void R_Water_StartFrame(void)
7252 {
7253         int i;
7254         int waterwidth, waterheight, texturewidth, textureheight;
7255         r_waterstate_waterplane_t *p;
7256
7257         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
7258                 return;
7259
7260         switch(vid.renderpath)
7261         {
7262         case RENDERPATH_GL20:
7263         case RENDERPATH_CGGL:
7264                 break;
7265         case RENDERPATH_GL13:
7266         case RENDERPATH_GL11:
7267                 return;
7268         }
7269
7270         // set waterwidth and waterheight to the water resolution that will be
7271         // used (often less than the screen resolution for faster rendering)
7272         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
7273         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
7274
7275         // calculate desired texture sizes
7276         // can't use water if the card does not support the texture size
7277         if (!r_water.integer || r_showsurfaces.integer)
7278                 texturewidth = textureheight = waterwidth = waterheight = 0;
7279         else if (vid.support.arb_texture_non_power_of_two)
7280         {
7281                 texturewidth = waterwidth;
7282                 textureheight = waterheight;
7283         }
7284         else
7285         {
7286                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
7287                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
7288         }
7289
7290         // allocate textures as needed
7291         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
7292         {
7293                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7294                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
7295                 {
7296                         if (p->texture_refraction)
7297                                 R_FreeTexture(p->texture_refraction);
7298                         p->texture_refraction = NULL;
7299                         if (p->texture_reflection)
7300                                 R_FreeTexture(p->texture_reflection);
7301                         p->texture_reflection = NULL;
7302                 }
7303                 memset(&r_waterstate, 0, sizeof(r_waterstate));
7304                 r_waterstate.texturewidth = texturewidth;
7305                 r_waterstate.textureheight = textureheight;
7306         }
7307
7308         if (r_waterstate.texturewidth)
7309         {
7310                 r_waterstate.enabled = true;
7311
7312                 // when doing a reduced render (HDR) we want to use a smaller area
7313                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
7314                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
7315
7316                 // set up variables that will be used in shader setup
7317                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7318                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7319                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7320                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7321         }
7322
7323         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7324         r_waterstate.numwaterplanes = 0;
7325 }
7326
7327 void R_Water_AddWaterPlane(msurface_t *surface)
7328 {
7329         int triangleindex, planeindex;
7330         const int *e;
7331         vec3_t vert[3];
7332         vec3_t normal;
7333         vec3_t center;
7334         mplane_t plane;
7335         r_waterstate_waterplane_t *p;
7336         texture_t *t = R_GetCurrentTexture(surface->texture);
7337         // just use the first triangle with a valid normal for any decisions
7338         VectorClear(normal);
7339         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
7340         {
7341                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
7342                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
7343                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
7344                 TriangleNormal(vert[0], vert[1], vert[2], normal);
7345                 if (VectorLength2(normal) >= 0.001)
7346                         break;
7347         }
7348
7349         VectorCopy(normal, plane.normal);
7350         VectorNormalize(plane.normal);
7351         plane.dist = DotProduct(vert[0], plane.normal);
7352         PlaneClassify(&plane);
7353         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
7354         {
7355                 // skip backfaces (except if nocullface is set)
7356                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
7357                         return;
7358                 VectorNegate(plane.normal, plane.normal);
7359                 plane.dist *= -1;
7360                 PlaneClassify(&plane);
7361         }
7362
7363
7364         // find a matching plane if there is one
7365         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7366                 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
7367                         break;
7368         if (planeindex >= r_waterstate.maxwaterplanes)
7369                 return; // nothing we can do, out of planes
7370
7371         // if this triangle does not fit any known plane rendered this frame, add one
7372         if (planeindex >= r_waterstate.numwaterplanes)
7373         {
7374                 // store the new plane
7375                 r_waterstate.numwaterplanes++;
7376                 p->plane = plane;
7377                 // clear materialflags and pvs
7378                 p->materialflags = 0;
7379                 p->pvsvalid = false;
7380         }
7381         // merge this surface's materialflags into the waterplane
7382         p->materialflags |= t->currentmaterialflags;
7383         // merge this surface's PVS into the waterplane
7384         VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
7385         if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
7386          && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
7387         {
7388                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
7389                 p->pvsvalid = true;
7390         }
7391 }
7392
7393 static void R_Water_ProcessPlanes(void)
7394 {
7395         r_refdef_view_t originalview;
7396         r_refdef_view_t myview;
7397         int planeindex;
7398         r_waterstate_waterplane_t *p;
7399
7400         originalview = r_refdef.view;
7401
7402         // make sure enough textures are allocated
7403         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7404         {
7405                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7406                 {
7407                         if (!p->texture_refraction)
7408                                 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);
7409                         if (!p->texture_refraction)
7410                                 goto error;
7411                 }
7412
7413                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7414                 {
7415                         if (!p->texture_reflection)
7416                                 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);
7417                         if (!p->texture_reflection)
7418                                 goto error;
7419                 }
7420         }
7421
7422         // render views
7423         r_refdef.view = originalview;
7424         r_refdef.view.showdebug = false;
7425         r_refdef.view.width = r_waterstate.waterwidth;
7426         r_refdef.view.height = r_waterstate.waterheight;
7427         r_refdef.view.useclipplane = true;
7428         myview = r_refdef.view;
7429         r_waterstate.renderingscene = true;
7430         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7431         {
7432                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7433                 {
7434                         r_refdef.view = myview;
7435                         // render reflected scene and copy into texture
7436                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
7437                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
7438                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
7439                         r_refdef.view.clipplane = p->plane;
7440                         // reverse the cullface settings for this render
7441                         r_refdef.view.cullface_front = GL_FRONT;
7442                         r_refdef.view.cullface_back = GL_BACK;
7443                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
7444                         {
7445                                 r_refdef.view.usecustompvs = true;
7446                                 if (p->pvsvalid)
7447                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7448                                 else
7449                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7450                         }
7451
7452                         R_ResetViewRendering3D();
7453                         R_ClearScreen(r_refdef.fogenabled);
7454                         R_View_Update();
7455                         R_RenderScene();
7456
7457                         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);
7458                 }
7459
7460                 // render the normal view scene and copy into texture
7461                 // (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)
7462                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7463                 {
7464                         r_waterstate.renderingrefraction = true;
7465                         r_refdef.view = myview;
7466                         r_refdef.view.clipplane = p->plane;
7467                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
7468                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
7469                         PlaneClassify(&r_refdef.view.clipplane);
7470
7471                         R_ResetViewRendering3D();
7472                         R_ClearScreen(r_refdef.fogenabled);
7473                         R_View_Update();
7474                         R_RenderScene();
7475
7476                         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);
7477                         r_waterstate.renderingrefraction = false;
7478                 }
7479
7480         }
7481         r_waterstate.renderingscene = false;
7482         r_refdef.view = originalview;
7483         R_ResetViewRendering3D();
7484         R_ClearScreen(r_refdef.fogenabled);
7485         R_View_Update();
7486         return;
7487 error:
7488         r_refdef.view = originalview;
7489         r_waterstate.renderingscene = false;
7490         Cvar_SetValueQuick(&r_water, 0);
7491         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
7492         return;
7493 }
7494
7495 void R_Bloom_StartFrame(void)
7496 {
7497         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
7498
7499         switch(vid.renderpath)
7500         {
7501         case RENDERPATH_GL20:
7502         case RENDERPATH_CGGL:
7503                 break;
7504         case RENDERPATH_GL13:
7505         case RENDERPATH_GL11:
7506                 return;
7507         }
7508
7509         // set bloomwidth and bloomheight to the bloom resolution that will be
7510         // used (often less than the screen resolution for faster rendering)
7511         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
7512         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
7513         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
7514         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
7515         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
7516
7517         // calculate desired texture sizes
7518         if (vid.support.arb_texture_non_power_of_two)
7519         {
7520                 screentexturewidth = r_refdef.view.width;
7521                 screentextureheight = r_refdef.view.height;
7522                 bloomtexturewidth = r_bloomstate.bloomwidth;
7523                 bloomtextureheight = r_bloomstate.bloomheight;
7524         }
7525         else
7526         {
7527                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
7528                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
7529                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
7530                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
7531         }
7532
7533         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))
7534         {
7535                 Cvar_SetValueQuick(&r_hdr, 0);
7536                 Cvar_SetValueQuick(&r_bloom, 0);
7537                 Cvar_SetValueQuick(&r_motionblur, 0);
7538                 Cvar_SetValueQuick(&r_damageblur, 0);
7539         }
7540
7541         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)))
7542                 screentexturewidth = screentextureheight = 0;
7543         if (!r_hdr.integer && !r_bloom.integer)
7544                 bloomtexturewidth = bloomtextureheight = 0;
7545
7546         // allocate textures as needed
7547         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
7548         {
7549                 if (r_bloomstate.texture_screen)
7550                         R_FreeTexture(r_bloomstate.texture_screen);
7551                 r_bloomstate.texture_screen = NULL;
7552                 r_bloomstate.screentexturewidth = screentexturewidth;
7553                 r_bloomstate.screentextureheight = screentextureheight;
7554                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
7555                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
7556         }
7557         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
7558         {
7559                 if (r_bloomstate.texture_bloom)
7560                         R_FreeTexture(r_bloomstate.texture_bloom);
7561                 r_bloomstate.texture_bloom = NULL;
7562                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
7563                 r_bloomstate.bloomtextureheight = bloomtextureheight;
7564                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
7565                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7566         }
7567
7568         // when doing a reduced render (HDR) we want to use a smaller area
7569         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
7570         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
7571         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
7572         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
7573         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
7574
7575         // set up a texcoord array for the full resolution screen image
7576         // (we have to keep this around to copy back during final render)
7577         r_bloomstate.screentexcoord2f[0] = 0;
7578         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7579         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7580         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7581         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7582         r_bloomstate.screentexcoord2f[5] = 0;
7583         r_bloomstate.screentexcoord2f[6] = 0;
7584         r_bloomstate.screentexcoord2f[7] = 0;
7585
7586         // set up a texcoord array for the reduced resolution bloom image
7587         // (which will be additive blended over the screen image)
7588         r_bloomstate.bloomtexcoord2f[0] = 0;
7589         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7590         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7591         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7592         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7593         r_bloomstate.bloomtexcoord2f[5] = 0;
7594         r_bloomstate.bloomtexcoord2f[6] = 0;
7595         r_bloomstate.bloomtexcoord2f[7] = 0;
7596
7597         if (r_hdr.integer || r_bloom.integer)
7598         {
7599                 r_bloomstate.enabled = true;
7600                 r_bloomstate.hdr = r_hdr.integer != 0;
7601         }
7602
7603         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);
7604 }
7605
7606 void R_Bloom_CopyBloomTexture(float colorscale)
7607 {
7608         r_refdef.stats.bloom++;
7609
7610         // scale down screen texture to the bloom texture size
7611         CHECKGLERROR
7612         R_SetViewport(&r_bloomstate.viewport);
7613         GL_BlendFunc(GL_ONE, GL_ZERO);
7614         GL_Color(colorscale, colorscale, colorscale, 1);
7615         // TODO: optimize with multitexture or GLSL
7616         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7617         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7618         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7619         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7620
7621         // we now have a bloom image in the framebuffer
7622         // copy it into the bloom image texture for later processing
7623         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);
7624         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7625 }
7626
7627 void R_Bloom_CopyHDRTexture(void)
7628 {
7629         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);
7630         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7631 }
7632
7633 void R_Bloom_MakeTexture(void)
7634 {
7635         int x, range, dir;
7636         float xoffset, yoffset, r, brighten;
7637
7638         r_refdef.stats.bloom++;
7639
7640         R_ResetViewRendering2D();
7641         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7642         R_Mesh_ColorPointer(NULL, 0, 0);
7643
7644         // we have a bloom image in the framebuffer
7645         CHECKGLERROR
7646         R_SetViewport(&r_bloomstate.viewport);
7647
7648         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
7649         {
7650                 x *= 2;
7651                 r = bound(0, r_bloom_colorexponent.value / x, 1);
7652                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7653                 GL_Color(r, r, r, 1);
7654                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7655                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7656                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7657                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7658
7659                 // copy the vertically blurred bloom view to a texture
7660                 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);
7661                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7662         }
7663
7664         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
7665         brighten = r_bloom_brighten.value;
7666         if (r_hdr.integer)
7667                 brighten *= r_hdr_range.value;
7668         brighten = sqrt(brighten);
7669         if(range >= 1)
7670                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
7671         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7672         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
7673
7674         for (dir = 0;dir < 2;dir++)
7675         {
7676                 // blend on at multiple vertical offsets to achieve a vertical blur
7677                 // TODO: do offset blends using GLSL
7678                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
7679                 GL_BlendFunc(GL_ONE, GL_ZERO);
7680                 for (x = -range;x <= range;x++)
7681                 {
7682                         if (!dir){xoffset = 0;yoffset = x;}
7683                         else {xoffset = x;yoffset = 0;}
7684                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
7685                         yoffset /= (float)r_bloomstate.bloomtextureheight;
7686                         // compute a texcoord array with the specified x and y offset
7687                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
7688                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7689                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7690                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7691                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7692                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
7693                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
7694                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
7695                         // this r value looks like a 'dot' particle, fading sharply to
7696                         // black at the edges
7697                         // (probably not realistic but looks good enough)
7698                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
7699                         //r = brighten/(range*2+1);
7700                         r = brighten / (range * 2 + 1);
7701                         if(range >= 1)
7702                                 r *= (1 - x*x/(float)(range*range));
7703                         GL_Color(r, r, r, 1);
7704                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7705                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7706                         GL_BlendFunc(GL_ONE, GL_ONE);
7707                 }
7708
7709                 // copy the vertically blurred bloom view to a texture
7710                 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);
7711                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7712         }
7713
7714         // apply subtract last
7715         // (just like it would be in a GLSL shader)
7716         if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
7717         {
7718                 GL_BlendFunc(GL_ONE, GL_ZERO);
7719                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7720                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7721                 GL_Color(1, 1, 1, 1);
7722                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7723                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7724
7725                 GL_BlendFunc(GL_ONE, GL_ONE);
7726                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
7727                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7728                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7729                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 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                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
7733
7734                 // copy the darkened bloom view to a texture
7735                 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);
7736                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7737         }
7738 }
7739
7740 void R_HDR_RenderBloomTexture(void)
7741 {
7742         int oldwidth, oldheight;
7743         float oldcolorscale;
7744
7745         oldcolorscale = r_refdef.view.colorscale;
7746         oldwidth = r_refdef.view.width;
7747         oldheight = r_refdef.view.height;
7748         r_refdef.view.width = r_bloomstate.bloomwidth;
7749         r_refdef.view.height = r_bloomstate.bloomheight;
7750
7751         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
7752         // TODO: add exposure compensation features
7753         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
7754
7755         r_refdef.view.showdebug = false;
7756         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
7757
7758         R_ResetViewRendering3D();
7759
7760         R_ClearScreen(r_refdef.fogenabled);
7761         if (r_timereport_active)
7762                 R_TimeReport("HDRclear");
7763
7764         R_View_Update();
7765         if (r_timereport_active)
7766                 R_TimeReport("visibility");
7767
7768         // only do secondary renders with HDR if r_hdr is 2 or higher
7769         r_waterstate.numwaterplanes = 0;
7770         if (r_waterstate.enabled && r_hdr.integer >= 2)
7771                 R_RenderWaterPlanes();
7772
7773         r_refdef.view.showdebug = true;
7774         R_RenderScene();
7775         r_waterstate.numwaterplanes = 0;
7776
7777         R_ResetViewRendering2D();
7778
7779         R_Bloom_CopyHDRTexture();
7780         R_Bloom_MakeTexture();
7781
7782         // restore the view settings
7783         r_refdef.view.width = oldwidth;
7784         r_refdef.view.height = oldheight;
7785         r_refdef.view.colorscale = oldcolorscale;
7786
7787         R_ResetViewRendering3D();
7788
7789         R_ClearScreen(r_refdef.fogenabled);
7790         if (r_timereport_active)
7791                 R_TimeReport("viewclear");
7792 }
7793
7794 static void R_BlendView(void)
7795 {
7796         unsigned int permutation;
7797         float uservecs[4][4];
7798
7799         switch (vid.renderpath)
7800         {
7801         case RENDERPATH_GL20:
7802         case RENDERPATH_CGGL:
7803                 permutation =
7804                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
7805                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
7806                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
7807                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
7808                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
7809
7810                 if (r_bloomstate.texture_screen)
7811                 {
7812                         // make sure the buffer is available
7813                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
7814
7815                         R_ResetViewRendering2D();
7816                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7817                         R_Mesh_ColorPointer(NULL, 0, 0);
7818
7819                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
7820                         {
7821                                 // declare variables
7822                                 float speed;
7823                                 static float avgspeed;
7824
7825                                 speed = VectorLength(cl.movement_velocity);
7826
7827                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
7828                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
7829
7830                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
7831                                 speed = bound(0, speed, 1);
7832                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
7833
7834                                 // calculate values into a standard alpha
7835                                 cl.motionbluralpha = 1 - exp(-
7836                                                 (
7837                                                  (r_motionblur.value * speed / 80)
7838                                                  +
7839                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
7840                                                 )
7841                                                 /
7842                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
7843                                            );
7844
7845                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
7846                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
7847                                 // apply the blur
7848                                 if (cl.motionbluralpha > 0)
7849                                 {
7850                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7851                                         GL_Color(1, 1, 1, cl.motionbluralpha);
7852                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7853                                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7854                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7855                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7856                                 }
7857                         }
7858
7859                         // copy view into the screen texture
7860                         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);
7861                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7862                 }
7863                 else if (!r_bloomstate.texture_bloom)
7864                 {
7865                         // we may still have to do view tint...
7866                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7867                         {
7868                                 // apply a color tint to the whole view
7869                                 R_ResetViewRendering2D();
7870                                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7871                                 R_Mesh_ColorPointer(NULL, 0, 0);
7872                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7873                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7874                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7875                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7876                         }
7877                         break; // no screen processing, no bloom, skip it
7878                 }
7879
7880                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
7881                 {
7882                         // render simple bloom effect
7883                         // copy the screen and shrink it and darken it for the bloom process
7884                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
7885                         // make the bloom texture
7886                         R_Bloom_MakeTexture();
7887                 }
7888
7889 #if _MSC_VER >= 1400
7890 #define sscanf sscanf_s
7891 #endif
7892                 memset(uservecs, 0, sizeof(uservecs));
7893                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
7894                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
7895                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
7896                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
7897
7898                 R_ResetViewRendering2D();
7899                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7900                 R_Mesh_ColorPointer(NULL, 0, 0);
7901                 GL_Color(1, 1, 1, 1);
7902                 GL_BlendFunc(GL_ONE, GL_ZERO);
7903                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7904                 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7905
7906                 switch(vid.renderpath)
7907                 {
7908                 case RENDERPATH_GL20:
7909                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
7910                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
7911                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
7912                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
7913                         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]);
7914                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
7915                         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]);
7916                         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]);
7917                         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]);
7918                         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]);
7919                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
7920                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
7921                         break;
7922                 case RENDERPATH_CGGL:
7923 #ifdef SUPPORTCG
7924                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
7925                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
7926                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
7927                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
7928                         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
7929                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
7930                         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
7931                         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
7932                         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
7933                         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
7934                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
7935                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
7936 #endif
7937                         break;
7938                 default:
7939                         break;
7940                 }
7941                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7942                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7943                 break;
7944         case RENDERPATH_GL13:
7945         case RENDERPATH_GL11:
7946                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7947                 {
7948                         // apply a color tint to the whole view
7949                         R_ResetViewRendering2D();
7950                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7951                         R_Mesh_ColorPointer(NULL, 0, 0);
7952                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7953                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7954                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7955                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7956                 }
7957                 break;
7958         }
7959 }
7960
7961 matrix4x4_t r_waterscrollmatrix;
7962
7963 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
7964 {
7965         if (r_refdef.fog_density)
7966         {
7967                 r_refdef.fogcolor[0] = r_refdef.fog_red;
7968                 r_refdef.fogcolor[1] = r_refdef.fog_green;
7969                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7970
7971                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7972                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7973                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7974                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7975
7976                 {
7977                         vec3_t fogvec;
7978                         VectorCopy(r_refdef.fogcolor, fogvec);
7979                         //   color.rgb *= ContrastBoost * SceneBrightness;
7980                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7981                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7982                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7983                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7984                 }
7985         }
7986 }
7987
7988 void R_UpdateVariables(void)
7989 {
7990         R_Textures_Frame();
7991
7992         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7993
7994         r_refdef.farclip = r_farclip_base.value;
7995         if (r_refdef.scene.worldmodel)
7996                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7997         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7998
7999         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
8000                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
8001         r_refdef.polygonfactor = 0;
8002         r_refdef.polygonoffset = 0;
8003         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8004         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8005
8006         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
8007         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
8008         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
8009         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
8010         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
8011         if (r_showsurfaces.integer)
8012         {
8013                 r_refdef.scene.rtworld = false;
8014                 r_refdef.scene.rtworldshadows = false;
8015                 r_refdef.scene.rtdlight = false;
8016                 r_refdef.scene.rtdlightshadows = false;
8017                 r_refdef.lightmapintensity = 0;
8018         }
8019
8020         if (gamemode == GAME_NEHAHRA)
8021         {
8022                 if (gl_fogenable.integer)
8023                 {
8024                         r_refdef.oldgl_fogenable = true;
8025                         r_refdef.fog_density = gl_fogdensity.value;
8026                         r_refdef.fog_red = gl_fogred.value;
8027                         r_refdef.fog_green = gl_foggreen.value;
8028                         r_refdef.fog_blue = gl_fogblue.value;
8029                         r_refdef.fog_alpha = 1;
8030                         r_refdef.fog_start = 0;
8031                         r_refdef.fog_end = gl_skyclip.value;
8032                         r_refdef.fog_height = 1<<30;
8033                         r_refdef.fog_fadedepth = 128;
8034                 }
8035                 else if (r_refdef.oldgl_fogenable)
8036                 {
8037                         r_refdef.oldgl_fogenable = false;
8038                         r_refdef.fog_density = 0;
8039                         r_refdef.fog_red = 0;
8040                         r_refdef.fog_green = 0;
8041                         r_refdef.fog_blue = 0;
8042                         r_refdef.fog_alpha = 0;
8043                         r_refdef.fog_start = 0;
8044                         r_refdef.fog_end = 0;
8045                         r_refdef.fog_height = 1<<30;
8046                         r_refdef.fog_fadedepth = 128;
8047                 }
8048         }
8049
8050         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
8051         r_refdef.fog_start = max(0, r_refdef.fog_start);
8052         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
8053
8054         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
8055
8056         if (r_refdef.fog_density && r_drawfog.integer)
8057         {
8058                 r_refdef.fogenabled = true;
8059                 // this is the point where the fog reaches 0.9986 alpha, which we
8060                 // consider a good enough cutoff point for the texture
8061                 // (0.9986 * 256 == 255.6)
8062                 if (r_fog_exp2.integer)
8063                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
8064                 else
8065                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
8066                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
8067                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
8068                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
8069                 // fog color was already set
8070                 // update the fog texture
8071                 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)
8072                         R_BuildFogTexture();
8073         }
8074         else
8075                 r_refdef.fogenabled = false;
8076
8077         switch(vid.renderpath)
8078         {
8079         case RENDERPATH_GL20:
8080         case RENDERPATH_CGGL:
8081                 if(v_glslgamma.integer && !vid_gammatables_trivial)
8082                 {
8083                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
8084                         {
8085                                 // build GLSL gamma texture
8086 #define RAMPWIDTH 256
8087                                 unsigned short ramp[RAMPWIDTH * 3];
8088                                 unsigned char rampbgr[RAMPWIDTH][4];
8089                                 int i;
8090
8091                                 r_texture_gammaramps_serial = vid_gammatables_serial;
8092
8093                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
8094                                 for(i = 0; i < RAMPWIDTH; ++i)
8095                                 {
8096                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8097                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8098                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
8099                                         rampbgr[i][3] = 0;
8100                                 }
8101                                 if (r_texture_gammaramps)
8102                                 {
8103                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
8104                                 }
8105                                 else
8106                                 {
8107                                         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);
8108                                 }
8109                         }
8110                 }
8111                 else
8112                 {
8113                         // remove GLSL gamma texture
8114                 }
8115                 break;
8116         case RENDERPATH_GL13:
8117         case RENDERPATH_GL11:
8118                 break;
8119         }
8120 }
8121
8122 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
8123 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
8124 /*
8125 ================
8126 R_SelectScene
8127 ================
8128 */
8129 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
8130         if( scenetype != r_currentscenetype ) {
8131                 // store the old scenetype
8132                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
8133                 r_currentscenetype = scenetype;
8134                 // move in the new scene
8135                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
8136         }
8137 }
8138
8139 /*
8140 ================
8141 R_GetScenePointer
8142 ================
8143 */
8144 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
8145 {
8146         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
8147         if( scenetype == r_currentscenetype ) {
8148                 return &r_refdef.scene;
8149         } else {
8150                 return &r_scenes_store[ scenetype ];
8151         }
8152 }
8153
8154 /*
8155 ================
8156 R_RenderView
8157 ================
8158 */
8159 void R_RenderView(void)
8160 {
8161         if (r_timereport_active)
8162                 R_TimeReport("start");
8163         r_textureframe++; // used only by R_GetCurrentTexture
8164         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8165
8166         if (!r_drawentities.integer)
8167                 r_refdef.scene.numentities = 0;
8168
8169         R_AnimCache_ClearCache();
8170         R_FrameData_NewFrame();
8171
8172         if (r_refdef.view.isoverlay)
8173         {
8174                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
8175                 GL_Clear( GL_DEPTH_BUFFER_BIT );
8176                 R_TimeReport("depthclear");
8177
8178                 r_refdef.view.showdebug = false;
8179
8180                 r_waterstate.enabled = false;
8181                 r_waterstate.numwaterplanes = 0;
8182
8183                 R_RenderScene();
8184
8185                 CHECKGLERROR
8186                 return;
8187         }
8188
8189         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
8190                 return; //Host_Error ("R_RenderView: NULL worldmodel");
8191
8192         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
8193
8194         // break apart the view matrix into vectors for various purposes
8195         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8196         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8197         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8198         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8199         // make an inverted copy of the view matrix for tracking sprites
8200         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8201
8202         R_Shadow_UpdateWorldLightSelection();
8203
8204         R_Bloom_StartFrame();
8205         R_Water_StartFrame();
8206
8207         CHECKGLERROR
8208         if (r_timereport_active)
8209                 R_TimeReport("viewsetup");
8210
8211         R_ResetViewRendering3D();
8212
8213         if (r_refdef.view.clear || r_refdef.fogenabled)
8214         {
8215                 R_ClearScreen(r_refdef.fogenabled);
8216                 if (r_timereport_active)
8217                         R_TimeReport("viewclear");
8218         }
8219         r_refdef.view.clear = true;
8220
8221         // this produces a bloom texture to be used in R_BlendView() later
8222         if (r_hdr.integer && r_bloomstate.bloomwidth)
8223         {
8224                 R_HDR_RenderBloomTexture();
8225                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
8226                 r_textureframe++; // used only by R_GetCurrentTexture
8227         }
8228
8229         r_refdef.view.showdebug = true;
8230
8231         R_View_Update();
8232         if (r_timereport_active)
8233                 R_TimeReport("visibility");
8234
8235         r_waterstate.numwaterplanes = 0;
8236         if (r_waterstate.enabled)
8237                 R_RenderWaterPlanes();
8238
8239         R_RenderScene();
8240         r_waterstate.numwaterplanes = 0;
8241
8242         R_BlendView();
8243         if (r_timereport_active)
8244                 R_TimeReport("blendview");
8245
8246         GL_Scissor(0, 0, vid.width, vid.height);
8247         GL_ScissorTest(false);
8248         CHECKGLERROR
8249 }
8250
8251 void R_RenderWaterPlanes(void)
8252 {
8253         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
8254         {
8255                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
8256                 if (r_timereport_active)
8257                         R_TimeReport("waterworld");
8258         }
8259
8260         // don't let sound skip if going slow
8261         if (r_refdef.scene.extraupdate)
8262                 S_ExtraUpdate ();
8263
8264         R_DrawModelsAddWaterPlanes();
8265         if (r_timereport_active)
8266                 R_TimeReport("watermodels");
8267
8268         if (r_waterstate.numwaterplanes)
8269         {
8270                 R_Water_ProcessPlanes();
8271                 if (r_timereport_active)
8272                         R_TimeReport("waterscenes");
8273         }
8274 }
8275
8276 extern void R_DrawLightningBeams (void);
8277 extern void VM_CL_AddPolygonsToMeshQueue (void);
8278 extern void R_DrawPortals (void);
8279 extern cvar_t cl_locs_show;
8280 static void R_DrawLocs(void);
8281 static void R_DrawEntityBBoxes(void);
8282 static void R_DrawModelDecals(void);
8283 extern void R_DrawModelShadows(void);
8284 extern void R_DrawModelShadowMaps(void);
8285 extern cvar_t cl_decals_newsystem;
8286 extern qboolean r_shadow_usingdeferredprepass;
8287 void R_RenderScene(void)
8288 {
8289         qboolean shadowmapping = false;
8290
8291         r_refdef.stats.renders++;
8292
8293         R_UpdateFogColor();
8294
8295         // don't let sound skip if going slow
8296         if (r_refdef.scene.extraupdate)
8297                 S_ExtraUpdate ();
8298
8299         R_MeshQueue_BeginScene();
8300
8301         R_SkyStartFrame();
8302
8303         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);
8304
8305         if (cl.csqc_vidvars.drawworld)
8306         {
8307                 // don't let sound skip if going slow
8308                 if (r_refdef.scene.extraupdate)
8309                         S_ExtraUpdate ();
8310
8311                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
8312                 {
8313                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
8314                         if (r_timereport_active)
8315                                 R_TimeReport("worldsky");
8316                 }
8317
8318                 if (R_DrawBrushModelsSky() && r_timereport_active)
8319                         R_TimeReport("bmodelsky");
8320
8321                 if (skyrendermasked && skyrenderlater)
8322                 {
8323                         // we have to force off the water clipping plane while rendering sky
8324                         R_SetupView(false);
8325                         R_Sky();
8326                         R_SetupView(true);
8327                         if (r_timereport_active)
8328                                 R_TimeReport("sky");
8329                 }
8330         }
8331
8332         R_AnimCache_CacheVisibleEntities();
8333         if (r_timereport_active)
8334                 R_TimeReport("animation");
8335
8336         R_Shadow_PrepareLights();
8337         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
8338                 R_Shadow_PrepareModelShadows();
8339         if (r_timereport_active)
8340                 R_TimeReport("preparelights");
8341
8342         if (R_Shadow_ShadowMappingEnabled())
8343                 shadowmapping = true;
8344
8345         if (r_shadow_usingdeferredprepass)
8346                 R_Shadow_DrawPrepass();
8347
8348         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
8349         {
8350                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
8351                 if (r_timereport_active)
8352                         R_TimeReport("worlddepth");
8353         }
8354         if (r_depthfirst.integer >= 2)
8355         {
8356                 R_DrawModelsDepth();
8357                 if (r_timereport_active)
8358                         R_TimeReport("modeldepth");
8359         }
8360
8361         if (r_shadows.integer > 0 && shadowmapping && r_refdef.lightmapintensity > 0)
8362         {
8363                 R_DrawModelShadowMaps();
8364                 R_ResetViewRendering3D();
8365                 // don't let sound skip if going slow
8366                 if (r_refdef.scene.extraupdate)
8367                         S_ExtraUpdate ();
8368         }
8369
8370         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
8371         {
8372                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
8373                 if (r_timereport_active)
8374                         R_TimeReport("world");
8375         }
8376
8377         // don't let sound skip if going slow
8378         if (r_refdef.scene.extraupdate)
8379                 S_ExtraUpdate ();
8380
8381         R_DrawModels();
8382         if (r_timereport_active)
8383                 R_TimeReport("models");
8384
8385         // don't let sound skip if going slow
8386         if (r_refdef.scene.extraupdate)
8387                 S_ExtraUpdate ();
8388
8389         if (r_shadows.integer > 0 && !shadowmapping && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8390         {
8391                 R_DrawModelShadows();
8392                 R_ResetViewRendering3D();
8393                 // don't let sound skip if going slow
8394                 if (r_refdef.scene.extraupdate)
8395                         S_ExtraUpdate ();
8396         }
8397
8398         if (!r_shadow_usingdeferredprepass)
8399         {
8400                 R_Shadow_DrawLights();
8401                 if (r_timereport_active)
8402                         R_TimeReport("rtlights");
8403         }
8404
8405         // don't let sound skip if going slow
8406         if (r_refdef.scene.extraupdate)
8407                 S_ExtraUpdate ();
8408
8409         if (r_shadows.integer > 0 && !shadowmapping && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8410         {
8411                 R_DrawModelShadows();
8412                 R_ResetViewRendering3D();
8413                 // don't let sound skip if going slow
8414                 if (r_refdef.scene.extraupdate)
8415                         S_ExtraUpdate ();
8416         }
8417
8418         if (cl.csqc_vidvars.drawworld)
8419         {
8420                 if (cl_decals_newsystem.integer)
8421                 {
8422                         R_DrawModelDecals();
8423                         if (r_timereport_active)
8424                                 R_TimeReport("modeldecals");
8425                 }
8426                 else
8427                 {
8428                         R_DrawDecals();
8429                         if (r_timereport_active)
8430                                 R_TimeReport("decals");
8431                 }
8432
8433                 R_DrawParticles();
8434                 if (r_timereport_active)
8435                         R_TimeReport("particles");
8436
8437                 R_DrawExplosions();
8438                 if (r_timereport_active)
8439                         R_TimeReport("explosions");
8440
8441                 R_DrawLightningBeams();
8442                 if (r_timereport_active)
8443                         R_TimeReport("lightning");
8444         }
8445
8446         VM_CL_AddPolygonsToMeshQueue();
8447
8448         if (r_refdef.view.showdebug)
8449         {
8450                 if (cl_locs_show.integer)
8451                 {
8452                         R_DrawLocs();
8453                         if (r_timereport_active)
8454                                 R_TimeReport("showlocs");
8455                 }
8456
8457                 if (r_drawportals.integer)
8458                 {
8459                         R_DrawPortals();
8460                         if (r_timereport_active)
8461                                 R_TimeReport("portals");
8462                 }
8463
8464                 if (r_showbboxes.value > 0)
8465                 {
8466                         R_DrawEntityBBoxes();
8467                         if (r_timereport_active)
8468                                 R_TimeReport("bboxes");
8469                 }
8470         }
8471
8472         R_MeshQueue_RenderTransparent();
8473         if (r_timereport_active)
8474                 R_TimeReport("drawtrans");
8475
8476         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))
8477         {
8478                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
8479                 if (r_timereport_active)
8480                         R_TimeReport("worlddebug");
8481                 R_DrawModelsDebug();
8482                 if (r_timereport_active)
8483                         R_TimeReport("modeldebug");
8484         }
8485
8486         if (cl.csqc_vidvars.drawworld)
8487         {
8488                 R_Shadow_DrawCoronas();
8489                 if (r_timereport_active)
8490                         R_TimeReport("coronas");
8491         }
8492
8493         // don't let sound skip if going slow
8494         if (r_refdef.scene.extraupdate)
8495                 S_ExtraUpdate ();
8496
8497         R_ResetViewRendering2D();
8498 }
8499
8500 static const unsigned short bboxelements[36] =
8501 {
8502         5, 1, 3, 5, 3, 7,
8503         6, 2, 0, 6, 0, 4,
8504         7, 3, 2, 7, 2, 6,
8505         4, 0, 1, 4, 1, 5,
8506         4, 5, 7, 4, 7, 6,
8507         1, 0, 2, 1, 2, 3,
8508 };
8509
8510 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
8511 {
8512         int i;
8513         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
8514
8515         RSurf_ActiveWorldEntity();
8516
8517         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8518         GL_DepthMask(false);
8519         GL_DepthRange(0, 1);
8520         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8521         R_Mesh_ResetTextureState();
8522
8523         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
8524         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
8525         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
8526         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
8527         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
8528         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
8529         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
8530         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
8531         R_FillColors(color4f, 8, cr, cg, cb, ca);
8532         if (r_refdef.fogenabled)
8533         {
8534                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
8535                 {
8536                         f1 = RSurf_FogVertex(v);
8537                         f2 = 1 - f1;
8538                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
8539                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
8540                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
8541                 }
8542         }
8543         R_Mesh_VertexPointer(vertex3f, 0, 0);
8544         R_Mesh_ColorPointer(color4f, 0, 0);
8545         R_Mesh_ResetTextureState();
8546         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8547         R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
8548 }
8549
8550 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8551 {
8552         int i;
8553         float color[4];
8554         prvm_edict_t *edict;
8555         prvm_prog_t *prog_save = prog;
8556
8557         // this function draws bounding boxes of server entities
8558         if (!sv.active)
8559                 return;
8560
8561         GL_CullFace(GL_NONE);
8562         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8563
8564         prog = 0;
8565         SV_VM_Begin();
8566         for (i = 0;i < numsurfaces;i++)
8567         {
8568                 edict = PRVM_EDICT_NUM(surfacelist[i]);
8569                 switch ((int)edict->fields.server->solid)
8570                 {
8571                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
8572                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
8573                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
8574                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
8575                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
8576                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
8577                 }
8578                 color[3] *= r_showbboxes.value;
8579                 color[3] = bound(0, color[3], 1);
8580                 GL_DepthTest(!r_showdisabledepthtest.integer);
8581                 GL_CullFace(r_refdef.view.cullface_front);
8582                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
8583         }
8584         SV_VM_End();
8585         prog = prog_save;
8586 }
8587
8588 static void R_DrawEntityBBoxes(void)
8589 {
8590         int i;
8591         prvm_edict_t *edict;
8592         vec3_t center;
8593         prvm_prog_t *prog_save = prog;
8594
8595         // this function draws bounding boxes of server entities
8596         if (!sv.active)
8597                 return;
8598
8599         prog = 0;
8600         SV_VM_Begin();
8601         for (i = 0;i < prog->num_edicts;i++)
8602         {
8603                 edict = PRVM_EDICT_NUM(i);
8604                 if (edict->priv.server->free)
8605                         continue;
8606                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
8607                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
8608                         continue;
8609                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
8610                         continue;
8611                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
8612                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
8613         }
8614         SV_VM_End();
8615         prog = prog_save;
8616 }
8617
8618 static const int nomodelelement3i[24] =
8619 {
8620         5, 2, 0,
8621         5, 1, 2,
8622         5, 0, 3,
8623         5, 3, 1,
8624         0, 2, 4,
8625         2, 1, 4,
8626         3, 0, 4,
8627         1, 3, 4
8628 };
8629
8630 static const unsigned short nomodelelement3s[24] =
8631 {
8632         5, 2, 0,
8633         5, 1, 2,
8634         5, 0, 3,
8635         5, 3, 1,
8636         0, 2, 4,
8637         2, 1, 4,
8638         3, 0, 4,
8639         1, 3, 4
8640 };
8641
8642 static const float nomodelvertex3f[6*3] =
8643 {
8644         -16,   0,   0,
8645          16,   0,   0,
8646           0, -16,   0,
8647           0,  16,   0,
8648           0,   0, -16,
8649           0,   0,  16
8650 };
8651
8652 static const float nomodelcolor4f[6*4] =
8653 {
8654         0.0f, 0.0f, 0.5f, 1.0f,
8655         0.0f, 0.0f, 0.5f, 1.0f,
8656         0.0f, 0.5f, 0.0f, 1.0f,
8657         0.0f, 0.5f, 0.0f, 1.0f,
8658         0.5f, 0.0f, 0.0f, 1.0f,
8659         0.5f, 0.0f, 0.0f, 1.0f
8660 };
8661
8662 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8663 {
8664         int i;
8665         float f1, f2, *c;
8666         float color4f[6*4];
8667
8668         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);
8669
8670         // this is only called once per entity so numsurfaces is always 1, and
8671         // surfacelist is always {0}, so this code does not handle batches
8672
8673         if (rsurface.ent_flags & RENDER_ADDITIVE)
8674         {
8675                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
8676                 GL_DepthMask(false);
8677         }
8678         else if (rsurface.colormod[3] < 1)
8679         {
8680                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8681                 GL_DepthMask(false);
8682         }
8683         else
8684         {
8685                 GL_BlendFunc(GL_ONE, GL_ZERO);
8686                 GL_DepthMask(true);
8687         }
8688         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8689         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8690         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8691         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8692         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8693         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
8694         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8695         R_Mesh_ColorPointer(color4f, 0, 0);
8696         for (i = 0, c = color4f;i < 6;i++, c += 4)
8697         {
8698                 c[0] *= rsurface.colormod[0];
8699                 c[1] *= rsurface.colormod[1];
8700                 c[2] *= rsurface.colormod[2];
8701                 c[3] *= rsurface.colormod[3];
8702         }
8703         if (r_refdef.fogenabled)
8704         {
8705                 for (i = 0, c = color4f;i < 6;i++, c += 4)
8706                 {
8707                         f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
8708                         f2 = 1 - f1;
8709                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8710                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8711                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8712                 }
8713         }
8714         R_Mesh_ResetTextureState();
8715         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
8716 }
8717
8718 void R_DrawNoModel(entity_render_t *ent)
8719 {
8720         vec3_t org;
8721         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8722         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8723                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8724         else
8725                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8726 }
8727
8728 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8729 {
8730         vec3_t right1, right2, diff, normal;
8731
8732         VectorSubtract (org2, org1, normal);
8733
8734         // calculate 'right' vector for start
8735         VectorSubtract (r_refdef.view.origin, org1, diff);
8736         CrossProduct (normal, diff, right1);
8737         VectorNormalize (right1);
8738
8739         // calculate 'right' vector for end
8740         VectorSubtract (r_refdef.view.origin, org2, diff);
8741         CrossProduct (normal, diff, right2);
8742         VectorNormalize (right2);
8743
8744         vert[ 0] = org1[0] + width * right1[0];
8745         vert[ 1] = org1[1] + width * right1[1];
8746         vert[ 2] = org1[2] + width * right1[2];
8747         vert[ 3] = org1[0] - width * right1[0];
8748         vert[ 4] = org1[1] - width * right1[1];
8749         vert[ 5] = org1[2] - width * right1[2];
8750         vert[ 6] = org2[0] - width * right2[0];
8751         vert[ 7] = org2[1] - width * right2[1];
8752         vert[ 8] = org2[2] - width * right2[2];
8753         vert[ 9] = org2[0] + width * right2[0];
8754         vert[10] = org2[1] + width * right2[1];
8755         vert[11] = org2[2] + width * right2[2];
8756 }
8757
8758 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)
8759 {
8760         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8761         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8762         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8763         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8764         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8765         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8766         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8767         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8768         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8769         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8770         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8771         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8772 }
8773
8774 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8775 {
8776         int i;
8777         float *vertex3f;
8778         float v[3];
8779         VectorSet(v, x, y, z);
8780         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8781                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8782                         break;
8783         if (i == mesh->numvertices)
8784         {
8785                 if (mesh->numvertices < mesh->maxvertices)
8786                 {
8787                         VectorCopy(v, vertex3f);
8788                         mesh->numvertices++;
8789                 }
8790                 return mesh->numvertices;
8791         }
8792         else
8793                 return i;
8794 }
8795
8796 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8797 {
8798         int i;
8799         int *e, element[3];
8800         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8801         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8802         e = mesh->element3i + mesh->numtriangles * 3;
8803         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8804         {
8805                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8806                 if (mesh->numtriangles < mesh->maxtriangles)
8807                 {
8808                         *e++ = element[0];
8809                         *e++ = element[1];
8810                         *e++ = element[2];
8811                         mesh->numtriangles++;
8812                 }
8813                 element[1] = element[2];
8814         }
8815 }
8816
8817 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8818 {
8819         int i;
8820         int *e, element[3];
8821         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8822         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8823         e = mesh->element3i + mesh->numtriangles * 3;
8824         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8825         {
8826                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8827                 if (mesh->numtriangles < mesh->maxtriangles)
8828                 {
8829                         *e++ = element[0];
8830                         *e++ = element[1];
8831                         *e++ = element[2];
8832                         mesh->numtriangles++;
8833                 }
8834                 element[1] = element[2];
8835         }
8836 }
8837
8838 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8839 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8840 {
8841         int planenum, planenum2;
8842         int w;
8843         int tempnumpoints;
8844         mplane_t *plane, *plane2;
8845         double maxdist;
8846         double temppoints[2][256*3];
8847         // figure out how large a bounding box we need to properly compute this brush
8848         maxdist = 0;
8849         for (w = 0;w < numplanes;w++)
8850                 maxdist = max(maxdist, fabs(planes[w].dist));
8851         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8852         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8853         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8854         {
8855                 w = 0;
8856                 tempnumpoints = 4;
8857                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8858                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8859                 {
8860                         if (planenum2 == planenum)
8861                                 continue;
8862                         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);
8863                         w = !w;
8864                 }
8865                 if (tempnumpoints < 3)
8866                         continue;
8867                 // generate elements forming a triangle fan for this polygon
8868                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8869         }
8870 }
8871
8872 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)
8873 {
8874         texturelayer_t *layer;
8875         layer = t->currentlayers + t->currentnumlayers++;
8876         layer->type = type;
8877         layer->depthmask = depthmask;
8878         layer->blendfunc1 = blendfunc1;
8879         layer->blendfunc2 = blendfunc2;
8880         layer->texture = texture;
8881         layer->texmatrix = *matrix;
8882         layer->color[0] = r;
8883         layer->color[1] = g;
8884         layer->color[2] = b;
8885         layer->color[3] = a;
8886 }
8887
8888 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8889 {
8890         double index, f;
8891         index = parms[2] + r_refdef.scene.time * parms[3];
8892         index -= floor(index);
8893         switch (func)
8894         {
8895         default:
8896         case Q3WAVEFUNC_NONE:
8897         case Q3WAVEFUNC_NOISE:
8898         case Q3WAVEFUNC_COUNT:
8899                 f = 0;
8900                 break;
8901         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8902         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8903         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8904         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8905         case Q3WAVEFUNC_TRIANGLE:
8906                 index *= 4;
8907                 f = index - floor(index);
8908                 if (index < 1)
8909                         f = f;
8910                 else if (index < 2)
8911                         f = 1 - f;
8912                 else if (index < 3)
8913                         f = -f;
8914                 else
8915                         f = -(1 - f);
8916                 break;
8917         }
8918         return (float)(parms[0] + parms[1] * f);
8919 }
8920
8921 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8922 {
8923         int w, h, idx;
8924         float f;
8925         float tcmat[12];
8926         matrix4x4_t matrix, temp;
8927         switch(tcmod->tcmod)
8928         {
8929                 case Q3TCMOD_COUNT:
8930                 case Q3TCMOD_NONE:
8931                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8932                                 matrix = r_waterscrollmatrix;
8933                         else
8934                                 matrix = identitymatrix;
8935                         break;
8936                 case Q3TCMOD_ENTITYTRANSLATE:
8937                         // this is used in Q3 to allow the gamecode to control texcoord
8938                         // scrolling on the entity, which is not supported in darkplaces yet.
8939                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8940                         break;
8941                 case Q3TCMOD_ROTATE:
8942                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8943                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
8944                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8945                         break;
8946                 case Q3TCMOD_SCALE:
8947                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8948                         break;
8949                 case Q3TCMOD_SCROLL:
8950                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
8951                         break;
8952                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8953                         w = (int) tcmod->parms[0];
8954                         h = (int) tcmod->parms[1];
8955                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
8956                         f = f - floor(f);
8957                         idx = (int) floor(f * w * h);
8958                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8959                         break;
8960                 case Q3TCMOD_STRETCH:
8961                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8962                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8963                         break;
8964                 case Q3TCMOD_TRANSFORM:
8965                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8966                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8967                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8968                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8969                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8970                         break;
8971                 case Q3TCMOD_TURBULENT:
8972                         // this is handled in the RSurf_PrepareVertices function
8973                         matrix = identitymatrix;
8974                         break;
8975         }
8976         temp = *texmatrix;
8977         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8978 }
8979
8980 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8981 {
8982         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
8983         char name[MAX_QPATH];
8984         skinframe_t *skinframe;
8985         unsigned char pixels[296*194];
8986         strlcpy(cache->name, skinname, sizeof(cache->name));
8987         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8988         if (developer_loading.integer)
8989                 Con_Printf("loading %s\n", name);
8990         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8991         if (!skinframe || !skinframe->base)
8992         {
8993                 unsigned char *f;
8994                 fs_offset_t filesize;
8995                 skinframe = NULL;
8996                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8997                 if (f)
8998                 {
8999                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
9000                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
9001                         Mem_Free(f);
9002                 }
9003         }
9004         cache->skinframe = skinframe;
9005 }
9006
9007 texture_t *R_GetCurrentTexture(texture_t *t)
9008 {
9009         int i;
9010         const entity_render_t *ent = rsurface.entity;
9011         dp_model_t *model = ent->model;
9012         q3shaderinfo_layer_tcmod_t *tcmod;
9013
9014         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
9015                 return t->currentframe;
9016         t->update_lastrenderframe = r_textureframe;
9017         t->update_lastrenderentity = (void *)ent;
9018
9019         // switch to an alternate material if this is a q1bsp animated material
9020         {
9021                 texture_t *texture = t;
9022                 int s = rsurface.ent_skinnum;
9023                 if ((unsigned int)s >= (unsigned int)model->numskins)
9024                         s = 0;
9025                 if (model->skinscenes)
9026                 {
9027                         if (model->skinscenes[s].framecount > 1)
9028                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
9029                         else
9030                                 s = model->skinscenes[s].firstframe;
9031                 }
9032                 if (s > 0)
9033                         t = t + s * model->num_surfaces;
9034                 if (t->animated)
9035                 {
9036                         // use an alternate animation if the entity's frame is not 0,
9037                         // and only if the texture has an alternate animation
9038                         if (rsurface.ent_alttextures && t->anim_total[1])
9039                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
9040                         else
9041                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
9042                 }
9043                 texture->currentframe = t;
9044         }
9045
9046         // update currentskinframe to be a qw skin or animation frame
9047         if (rsurface.ent_qwskin >= 0)
9048         {
9049                 i = rsurface.ent_qwskin;
9050                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
9051                 {
9052                         r_qwskincache_size = cl.maxclients;
9053                         if (r_qwskincache)
9054                                 Mem_Free(r_qwskincache);
9055                         r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
9056                 }
9057                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
9058                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
9059                 t->currentskinframe = r_qwskincache[i].skinframe;
9060                 if (t->currentskinframe == NULL)
9061                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9062         }
9063         else if (t->numskinframes >= 2)
9064                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9065         if (t->backgroundnumskinframes >= 2)
9066                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
9067
9068         t->currentmaterialflags = t->basematerialflags;
9069         t->currentalpha = rsurface.colormod[3];
9070         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
9071                 t->currentalpha *= r_wateralpha.value;
9072         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
9073                 t->currentalpha *= t->r_water_wateralpha;
9074         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
9075                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
9076         if (!(rsurface.ent_flags & RENDER_LIGHT))
9077                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
9078         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
9079         {
9080                 // pick a model lighting mode
9081                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
9082                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
9083                 else
9084                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
9085         }
9086         if (rsurface.ent_flags & RENDER_ADDITIVE)
9087                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9088         else if (t->currentalpha < 1)
9089                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9090         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
9091                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
9092         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
9093                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
9094         if (t->backgroundnumskinframes)
9095                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
9096         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
9097         {
9098                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
9099                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
9100         }
9101         else
9102                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
9103         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
9104                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
9105
9106         // there is no tcmod
9107         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9108         {
9109                 t->currenttexmatrix = r_waterscrollmatrix;
9110                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
9111         }
9112         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
9113         {
9114                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
9115                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
9116         }
9117
9118         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9119                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
9120         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9121                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
9122
9123         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
9124         if (t->currentskinframe->qpixels)
9125                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
9126         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
9127         if (!t->basetexture)
9128                 t->basetexture = r_texture_notexture;
9129         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
9130         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
9131         t->nmaptexture = t->currentskinframe->nmap;
9132         if (!t->nmaptexture)
9133                 t->nmaptexture = r_texture_blanknormalmap;
9134         t->glosstexture = r_texture_black;
9135         t->glowtexture = t->currentskinframe->glow;
9136         t->fogtexture = t->currentskinframe->fog;
9137         t->reflectmasktexture = t->currentskinframe->reflect;
9138         if (t->backgroundnumskinframes)
9139         {
9140                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
9141                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
9142                 t->backgroundglosstexture = r_texture_black;
9143                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
9144                 if (!t->backgroundnmaptexture)
9145                         t->backgroundnmaptexture = r_texture_blanknormalmap;
9146         }
9147         else
9148         {
9149                 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
9150                 t->backgroundnmaptexture = r_texture_blanknormalmap;
9151                 t->backgroundglosstexture = r_texture_black;
9152                 t->backgroundglowtexture = NULL;
9153         }
9154         t->specularpower = r_shadow_glossexponent.value;
9155         // TODO: store reference values for these in the texture?
9156         t->specularscale = 0;
9157         if (r_shadow_gloss.integer > 0)
9158         {
9159                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
9160                 {
9161                         if (r_shadow_glossintensity.value > 0)
9162                         {
9163                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
9164                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
9165                                 t->specularscale = r_shadow_glossintensity.value;
9166                         }
9167                 }
9168                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
9169                 {
9170                         t->glosstexture = r_texture_white;
9171                         t->backgroundglosstexture = r_texture_white;
9172                         t->specularscale = r_shadow_gloss2intensity.value;
9173                         t->specularpower = r_shadow_gloss2exponent.value;
9174                 }
9175         }
9176         t->specularscale *= t->specularscalemod;
9177         t->specularpower *= t->specularpowermod;
9178
9179         // lightmaps mode looks bad with dlights using actual texturing, so turn
9180         // off the colormap and glossmap, but leave the normalmap on as it still
9181         // accurately represents the shading involved
9182         if (gl_lightmaps.integer)
9183         {
9184                 t->basetexture = r_texture_grey128;
9185                 t->pantstexture = r_texture_black;
9186                 t->shirttexture = r_texture_black;
9187                 t->nmaptexture = r_texture_blanknormalmap;
9188                 t->glosstexture = r_texture_black;
9189                 t->glowtexture = NULL;
9190                 t->fogtexture = NULL;
9191                 t->reflectmasktexture = NULL;
9192                 t->backgroundbasetexture = NULL;
9193                 t->backgroundnmaptexture = r_texture_blanknormalmap;
9194                 t->backgroundglosstexture = r_texture_black;
9195                 t->backgroundglowtexture = NULL;
9196                 t->specularscale = 0;
9197                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
9198         }
9199
9200         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
9201         VectorClear(t->dlightcolor);
9202         t->currentnumlayers = 0;
9203         if (t->currentmaterialflags & MATERIALFLAG_WALL)
9204         {
9205                 int blendfunc1, blendfunc2;
9206                 qboolean depthmask;
9207                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
9208                 {
9209                         blendfunc1 = GL_SRC_ALPHA;
9210                         blendfunc2 = GL_ONE;
9211                 }
9212                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
9213                 {
9214                         blendfunc1 = GL_SRC_ALPHA;
9215                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
9216                 }
9217                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9218                 {
9219                         blendfunc1 = t->customblendfunc[0];
9220                         blendfunc2 = t->customblendfunc[1];
9221                 }
9222                 else
9223                 {
9224                         blendfunc1 = GL_ONE;
9225                         blendfunc2 = GL_ZERO;
9226                 }
9227                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
9228                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9229                 {
9230                         // fullbright is not affected by r_refdef.lightmapintensity
9231                         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]);
9232                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9233                                 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]);
9234                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9235                                 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]);
9236                 }
9237                 else
9238                 {
9239                         vec3_t ambientcolor;
9240                         float colorscale;
9241                         // set the color tint used for lights affecting this surface
9242                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
9243                         colorscale = 2;
9244                         // q3bsp has no lightmap updates, so the lightstylevalue that
9245                         // would normally be baked into the lightmap must be
9246                         // applied to the color
9247                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
9248                         if (model->type == mod_brushq3)
9249                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
9250                         colorscale *= r_refdef.lightmapintensity;
9251                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
9252                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
9253                         // basic lit geometry
9254                         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]);
9255                         // add pants/shirt if needed
9256                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9257                                 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]);
9258                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9259                                 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]);
9260                         // now add ambient passes if needed
9261                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
9262                         {
9263                                 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]);
9264                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9265                                         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]);
9266                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9267                                         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]);
9268                         }
9269                 }
9270                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
9271                         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]);
9272                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
9273                 {
9274                         // if this is opaque use alpha blend which will darken the earlier
9275                         // passes cheaply.
9276                         //
9277                         // if this is an alpha blended material, all the earlier passes
9278                         // were darkened by fog already, so we only need to add the fog
9279                         // color ontop through the fog mask texture
9280                         //
9281                         // if this is an additive blended material, all the earlier passes
9282                         // were darkened by fog already, and we should not add fog color
9283                         // (because the background was not darkened, there is no fog color
9284                         // that was lost behind it).
9285                         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]);
9286                 }
9287         }
9288
9289         return t->currentframe;
9290 }
9291
9292 rsurfacestate_t rsurface;
9293
9294 void R_Mesh_ResizeArrays(int newvertices)
9295 {
9296         float *base;
9297         if (rsurface.array_size >= newvertices)
9298                 return;
9299         if (rsurface.array_modelvertex3f)
9300                 Mem_Free(rsurface.array_modelvertex3f);
9301         rsurface.array_size = (newvertices + 1023) & ~1023;
9302         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
9303         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
9304         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
9305         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
9306         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
9307         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
9308         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
9309         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
9310         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
9311         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
9312         rsurface.array_color4f           = base + rsurface.array_size * 27;
9313         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
9314 }
9315
9316 void RSurf_ActiveWorldEntity(void)
9317 {
9318         dp_model_t *model = r_refdef.scene.worldmodel;
9319         //if (rsurface.entity == r_refdef.scene.worldentity)
9320         //      return;
9321         rsurface.entity = r_refdef.scene.worldentity;
9322         rsurface.skeleton = NULL;
9323         rsurface.ent_skinnum = 0;
9324         rsurface.ent_qwskin = -1;
9325         rsurface.ent_shadertime = 0;
9326         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
9327         if (rsurface.array_size < model->surfmesh.num_vertices)
9328                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9329         rsurface.matrix = identitymatrix;
9330         rsurface.inversematrix = identitymatrix;
9331         rsurface.matrixscale = 1;
9332         rsurface.inversematrixscale = 1;
9333         R_EntityMatrix(&identitymatrix);
9334         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
9335         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
9336         rsurface.fograngerecip = r_refdef.fograngerecip;
9337         rsurface.fogheightfade = r_refdef.fogheightfade;
9338         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
9339         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9340         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9341         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9342         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9343         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9344         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9345         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
9346         rsurface.colormod[3] = 1;
9347         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);
9348         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9349         rsurface.frameblend[0].lerp = 1;
9350         rsurface.ent_alttextures = false;
9351         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9352         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9353         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
9354         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9355         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9356         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9357         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9358         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9359         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9360         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9361         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9362         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
9363         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9364         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9365         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
9366         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9367         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9368         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
9369         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9370         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9371         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
9372         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9373         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9374         rsurface.modelelement3i = model->surfmesh.data_element3i;
9375         rsurface.modelelement3s = model->surfmesh.data_element3s;
9376         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9377         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9378         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9379         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9380         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9381         rsurface.modelsurfaces = model->data_surfaces;
9382         rsurface.generatedvertex = false;
9383         rsurface.vertex3f  = rsurface.modelvertex3f;
9384         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9385         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9386         rsurface.svector3f = rsurface.modelsvector3f;
9387         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9388         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9389         rsurface.tvector3f = rsurface.modeltvector3f;
9390         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9391         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9392         rsurface.normal3f  = rsurface.modelnormal3f;
9393         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9394         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9395         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9396 }
9397
9398 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
9399 {
9400         dp_model_t *model = ent->model;
9401         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
9402         //      return;
9403         rsurface.entity = (entity_render_t *)ent;
9404         rsurface.skeleton = ent->skeleton;
9405         rsurface.ent_skinnum = ent->skinnum;
9406         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;
9407         rsurface.ent_shadertime = ent->shadertime;
9408         rsurface.ent_flags = ent->flags;
9409         if (rsurface.array_size < model->surfmesh.num_vertices)
9410                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9411         rsurface.matrix = ent->matrix;
9412         rsurface.inversematrix = ent->inversematrix;
9413         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9414         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9415         R_EntityMatrix(&rsurface.matrix);
9416         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9417         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9418         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9419         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9420         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9421         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9422         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
9423         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
9424         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
9425         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
9426         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
9427         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
9428         rsurface.colormod[3] = ent->alpha;
9429         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
9430         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
9431         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
9432         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9433         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9434         if (ent->model->brush.submodel && !prepass)
9435         {
9436                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
9437                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
9438         }
9439         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
9440         {
9441                 if (ent->animcache_vertex3f && !r_framedata_failed)
9442                 {
9443                         rsurface.modelvertex3f = ent->animcache_vertex3f;
9444                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
9445                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
9446                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
9447                 }
9448                 else if (wanttangents)
9449                 {
9450                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9451                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9452                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9453                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9454                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
9455                 }
9456                 else if (wantnormals)
9457                 {
9458                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9459                         rsurface.modelsvector3f = NULL;
9460                         rsurface.modeltvector3f = NULL;
9461                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9462                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
9463                 }
9464                 else
9465                 {
9466                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9467                         rsurface.modelsvector3f = NULL;
9468                         rsurface.modeltvector3f = NULL;
9469                         rsurface.modelnormal3f = NULL;
9470                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
9471                 }
9472                 rsurface.modelvertex3f_bufferobject = 0;
9473                 rsurface.modelvertex3f_bufferoffset = 0;
9474                 rsurface.modelsvector3f_bufferobject = 0;
9475                 rsurface.modelsvector3f_bufferoffset = 0;
9476                 rsurface.modeltvector3f_bufferobject = 0;
9477                 rsurface.modeltvector3f_bufferoffset = 0;
9478                 rsurface.modelnormal3f_bufferobject = 0;
9479                 rsurface.modelnormal3f_bufferoffset = 0;
9480                 rsurface.generatedvertex = true;
9481         }
9482         else
9483         {
9484                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
9485                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9486                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9487                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9488                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9489                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9490                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9491                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9492                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9493                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
9494                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9495                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9496                 rsurface.generatedvertex = false;
9497         }
9498         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
9499         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9500         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9501         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
9502         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9503         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9504         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
9505         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9506         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9507         rsurface.modelelement3i = model->surfmesh.data_element3i;
9508         rsurface.modelelement3s = model->surfmesh.data_element3s;
9509         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9510         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9511         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9512         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9513         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9514         rsurface.modelsurfaces = model->data_surfaces;
9515         rsurface.vertex3f  = rsurface.modelvertex3f;
9516         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9517         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9518         rsurface.svector3f = rsurface.modelsvector3f;
9519         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9520         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9521         rsurface.tvector3f = rsurface.modeltvector3f;
9522         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9523         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9524         rsurface.normal3f  = rsurface.modelnormal3f;
9525         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9526         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9527         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9528 }
9529
9530 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)
9531 {
9532         rsurface.entity = r_refdef.scene.worldentity;
9533         rsurface.skeleton = NULL;
9534         rsurface.ent_skinnum = 0;
9535         rsurface.ent_qwskin = -1;
9536         rsurface.ent_shadertime = shadertime;
9537         rsurface.ent_flags = entflags;
9538         rsurface.modelnum_vertices = numvertices;
9539         rsurface.modelnum_triangles = numtriangles;
9540         if (rsurface.array_size < rsurface.modelnum_vertices)
9541                 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
9542         rsurface.matrix = *matrix;
9543         rsurface.inversematrix = *inversematrix;
9544         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9545         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9546         R_EntityMatrix(&rsurface.matrix);
9547         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9548         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9549         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9550         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9551         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9552         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9553         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9554         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9555         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9556         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9557         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9558         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
9559         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);
9560         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9561         rsurface.frameblend[0].lerp = 1;
9562         rsurface.ent_alttextures = false;
9563         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9564         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9565         if (wanttangents)
9566         {
9567                 rsurface.modelvertex3f = vertex3f;
9568                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
9569                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
9570                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9571         }
9572         else if (wantnormals)
9573         {
9574                 rsurface.modelvertex3f = vertex3f;
9575                 rsurface.modelsvector3f = NULL;
9576                 rsurface.modeltvector3f = NULL;
9577                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9578         }
9579         else
9580         {
9581                 rsurface.modelvertex3f = vertex3f;
9582                 rsurface.modelsvector3f = NULL;
9583                 rsurface.modeltvector3f = NULL;
9584                 rsurface.modelnormal3f = NULL;
9585         }
9586         rsurface.modelvertex3f_bufferobject = 0;
9587         rsurface.modelvertex3f_bufferoffset = 0;
9588         rsurface.modelsvector3f_bufferobject = 0;
9589         rsurface.modelsvector3f_bufferoffset = 0;
9590         rsurface.modeltvector3f_bufferobject = 0;
9591         rsurface.modeltvector3f_bufferoffset = 0;
9592         rsurface.modelnormal3f_bufferobject = 0;
9593         rsurface.modelnormal3f_bufferoffset = 0;
9594         rsurface.generatedvertex = true;
9595         rsurface.modellightmapcolor4f  = color4f;
9596         rsurface.modellightmapcolor4f_bufferobject = 0;
9597         rsurface.modellightmapcolor4f_bufferoffset = 0;
9598         rsurface.modeltexcoordtexture2f  = texcoord2f;
9599         rsurface.modeltexcoordtexture2f_bufferobject = 0;
9600         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9601         rsurface.modeltexcoordlightmap2f  = NULL;
9602         rsurface.modeltexcoordlightmap2f_bufferobject = 0;
9603         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9604         rsurface.modelelement3i = element3i;
9605         rsurface.modelelement3s = element3s;
9606         rsurface.modelelement3i_bufferobject = 0;
9607         rsurface.modelelement3s_bufferobject = 0;
9608         rsurface.modellightmapoffsets = NULL;
9609         rsurface.modelsurfaces = NULL;
9610         rsurface.vertex3f  = rsurface.modelvertex3f;
9611         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9612         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9613         rsurface.svector3f = rsurface.modelsvector3f;
9614         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9615         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9616         rsurface.tvector3f = rsurface.modeltvector3f;
9617         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9618         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9619         rsurface.normal3f  = rsurface.modelnormal3f;
9620         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9621         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9622         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9623
9624         if (rsurface.modelnum_vertices && rsurface.modelelement3i)
9625         {
9626                 if ((wantnormals || wanttangents) && !normal3f)
9627                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9628                 if (wanttangents && !svector3f)
9629                         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);
9630         }
9631 }
9632
9633 float RSurf_FogPoint(const float *v)
9634 {
9635         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9636         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9637         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9638         float FogHeightFade = r_refdef.fogheightfade;
9639         float fogfrac;
9640         unsigned int fogmasktableindex;
9641         if (r_refdef.fogplaneviewabove)
9642                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9643         else
9644                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9645         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9646         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9647 }
9648
9649 float RSurf_FogVertex(const float *v)
9650 {
9651         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9652         float FogPlaneViewDist = rsurface.fogplaneviewdist;
9653         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9654         float FogHeightFade = rsurface.fogheightfade;
9655         float fogfrac;
9656         unsigned int fogmasktableindex;
9657         if (r_refdef.fogplaneviewabove)
9658                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9659         else
9660                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9661         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9662         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9663 }
9664
9665 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9666 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9667 {
9668         int deformindex;
9669         int texturesurfaceindex;
9670         int i, j;
9671         float amplitude;
9672         float animpos;
9673         float scale;
9674         const float *v1, *in_tc;
9675         float *out_tc;
9676         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9677         float waveparms[4];
9678         q3shaderinfo_deform_t *deform;
9679         // 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
9680         if (rsurface.generatedvertex)
9681         {
9682                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
9683                         generatenormals = true;
9684                 for (i = 0;i < Q3MAXDEFORMS;i++)
9685                 {
9686                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
9687                         {
9688                                 generatetangents = true;
9689                                 generatenormals = true;
9690                         }
9691                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
9692                                 generatenormals = true;
9693                 }
9694                 if (generatenormals && !rsurface.modelnormal3f)
9695                 {
9696                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9697                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
9698                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
9699                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9700                 }
9701                 if (generatetangents && !rsurface.modelsvector3f)
9702                 {
9703                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9704                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
9705                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
9706                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9707                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
9708                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
9709                         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);
9710                 }
9711         }
9712         rsurface.vertex3f  = rsurface.modelvertex3f;
9713         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9714         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9715         rsurface.svector3f = rsurface.modelsvector3f;
9716         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9717         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9718         rsurface.tvector3f = rsurface.modeltvector3f;
9719         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9720         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9721         rsurface.normal3f  = rsurface.modelnormal3f;
9722         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9723         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9724         // if vertices are deformed (sprite flares and things in maps, possibly
9725         // water waves, bulges and other deformations), generate them into
9726         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
9727         // (may be static model data or generated data for an animated model, or
9728         //  the previous deform pass)
9729         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
9730         {
9731                 switch (deform->deform)
9732                 {
9733                 default:
9734                 case Q3DEFORM_PROJECTIONSHADOW:
9735                 case Q3DEFORM_TEXT0:
9736                 case Q3DEFORM_TEXT1:
9737                 case Q3DEFORM_TEXT2:
9738                 case Q3DEFORM_TEXT3:
9739                 case Q3DEFORM_TEXT4:
9740                 case Q3DEFORM_TEXT5:
9741                 case Q3DEFORM_TEXT6:
9742                 case Q3DEFORM_TEXT7:
9743                 case Q3DEFORM_NONE:
9744                         break;
9745                 case Q3DEFORM_AUTOSPRITE:
9746                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9747                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9748                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9749                         VectorNormalize(newforward);
9750                         VectorNormalize(newright);
9751                         VectorNormalize(newup);
9752                         // make deformed versions of only the model vertices used by the specified surfaces
9753                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9754                         {
9755                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9756                                 // a single autosprite surface can contain multiple sprites...
9757                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9758                                 {
9759                                         VectorClear(center);
9760                                         for (i = 0;i < 4;i++)
9761                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9762                                         VectorScale(center, 0.25f, center);
9763                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
9764                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
9765                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
9766                                         for (i = 0;i < 4;i++)
9767                                         {
9768                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
9769                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9770                                         }
9771                                 }
9772                                 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);
9773                                 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);
9774                         }
9775                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9776                         rsurface.vertex3f_bufferobject = 0;
9777                         rsurface.vertex3f_bufferoffset = 0;
9778                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9779                         rsurface.svector3f_bufferobject = 0;
9780                         rsurface.svector3f_bufferoffset = 0;
9781                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9782                         rsurface.tvector3f_bufferobject = 0;
9783                         rsurface.tvector3f_bufferoffset = 0;
9784                         rsurface.normal3f = rsurface.array_deformednormal3f;
9785                         rsurface.normal3f_bufferobject = 0;
9786                         rsurface.normal3f_bufferoffset = 0;
9787                         break;
9788                 case Q3DEFORM_AUTOSPRITE2:
9789                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9790                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9791                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9792                         VectorNormalize(newforward);
9793                         VectorNormalize(newright);
9794                         VectorNormalize(newup);
9795                         // make deformed versions of only the model vertices used by the specified surfaces
9796                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9797                         {
9798                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9799                                 const float *v1, *v2;
9800                                 vec3_t start, end;
9801                                 float f, l;
9802                                 struct
9803                                 {
9804                                         float length2;
9805                                         const float *v1;
9806                                         const float *v2;
9807                                 }
9808                                 shortest[2];
9809                                 memset(shortest, 0, sizeof(shortest));
9810                                 // a single autosprite surface can contain multiple sprites...
9811                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9812                                 {
9813                                         VectorClear(center);
9814                                         for (i = 0;i < 4;i++)
9815                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9816                                         VectorScale(center, 0.25f, center);
9817                                         // find the two shortest edges, then use them to define the
9818                                         // axis vectors for rotating around the central axis
9819                                         for (i = 0;i < 6;i++)
9820                                         {
9821                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
9822                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
9823 #if 0
9824                                                 Debug_PolygonBegin(NULL, 0);
9825                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
9826                                                 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);
9827                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
9828                                                 Debug_PolygonEnd();
9829 #endif
9830                                                 l = VectorDistance2(v1, v2);
9831                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9832                                                 if (v1[2] != v2[2])
9833                                                         l += (1.0f / 1024.0f);
9834                                                 if (shortest[0].length2 > l || i == 0)
9835                                                 {
9836                                                         shortest[1] = shortest[0];
9837                                                         shortest[0].length2 = l;
9838                                                         shortest[0].v1 = v1;
9839                                                         shortest[0].v2 = v2;
9840                                                 }
9841                                                 else if (shortest[1].length2 > l || i == 1)
9842                                                 {
9843                                                         shortest[1].length2 = l;
9844                                                         shortest[1].v1 = v1;
9845                                                         shortest[1].v2 = v2;
9846                                                 }
9847                                         }
9848                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9849                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9850 #if 0
9851                                         Debug_PolygonBegin(NULL, 0);
9852                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
9853                                         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);
9854                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
9855                                         Debug_PolygonEnd();
9856 #endif
9857                                         // this calculates the right vector from the shortest edge
9858                                         // and the up vector from the edge midpoints
9859                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9860                                         VectorNormalize(right);
9861                                         VectorSubtract(end, start, up);
9862                                         VectorNormalize(up);
9863                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9864                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9865                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9866                                         VectorNegate(forward, forward);
9867                                         VectorReflect(forward, 0, up, forward);
9868                                         VectorNormalize(forward);
9869                                         CrossProduct(up, forward, newright);
9870                                         VectorNormalize(newright);
9871 #if 0
9872                                         Debug_PolygonBegin(NULL, 0);
9873                                         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);
9874                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
9875                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
9876                                         Debug_PolygonEnd();
9877 #endif
9878 #if 0
9879                                         Debug_PolygonBegin(NULL, 0);
9880                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
9881                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
9882                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
9883                                         Debug_PolygonEnd();
9884 #endif
9885                                         // rotate the quad around the up axis vector, this is made
9886                                         // especially easy by the fact we know the quad is flat,
9887                                         // so we only have to subtract the center position and
9888                                         // measure distance along the right vector, and then
9889                                         // multiply that by the newright vector and add back the
9890                                         // center position
9891                                         // we also need to subtract the old position to undo the
9892                                         // displacement from the center, which we do with a
9893                                         // DotProduct, the subtraction/addition of center is also
9894                                         // optimized into DotProducts here
9895                                         l = DotProduct(right, center);
9896                                         for (i = 0;i < 4;i++)
9897                                         {
9898                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
9899                                                 f = DotProduct(right, v1) - l;
9900                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9901                                         }
9902                                 }
9903                                 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);
9904                                 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);
9905                         }
9906                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9907                         rsurface.vertex3f_bufferobject = 0;
9908                         rsurface.vertex3f_bufferoffset = 0;
9909                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9910                         rsurface.svector3f_bufferobject = 0;
9911                         rsurface.svector3f_bufferoffset = 0;
9912                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9913                         rsurface.tvector3f_bufferobject = 0;
9914                         rsurface.tvector3f_bufferoffset = 0;
9915                         rsurface.normal3f = rsurface.array_deformednormal3f;
9916                         rsurface.normal3f_bufferobject = 0;
9917                         rsurface.normal3f_bufferoffset = 0;
9918                         break;
9919                 case Q3DEFORM_NORMAL:
9920                         // deform the normals to make reflections wavey
9921                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9922                         {
9923                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9924                                 for (j = 0;j < surface->num_vertices;j++)
9925                                 {
9926                                         float vertex[3];
9927                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
9928                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
9929                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
9930                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9931                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9932                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9933                                         VectorNormalize(normal);
9934                                 }
9935                                 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);
9936                         }
9937                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9938                         rsurface.svector3f_bufferobject = 0;
9939                         rsurface.svector3f_bufferoffset = 0;
9940                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9941                         rsurface.tvector3f_bufferobject = 0;
9942                         rsurface.tvector3f_bufferoffset = 0;
9943                         rsurface.normal3f = rsurface.array_deformednormal3f;
9944                         rsurface.normal3f_bufferobject = 0;
9945                         rsurface.normal3f_bufferoffset = 0;
9946                         break;
9947                 case Q3DEFORM_WAVE:
9948                         // deform vertex array to make wavey water and flags and such
9949                         waveparms[0] = deform->waveparms[0];
9950                         waveparms[1] = deform->waveparms[1];
9951                         waveparms[2] = deform->waveparms[2];
9952                         waveparms[3] = deform->waveparms[3];
9953                         // this is how a divisor of vertex influence on deformation
9954                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9955                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9956                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9957                         {
9958                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9959                                 for (j = 0;j < surface->num_vertices;j++)
9960                                 {
9961                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
9962                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9963                                         // if the wavefunc depends on time, evaluate it per-vertex
9964                                         if (waveparms[3])
9965                                         {
9966                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
9967                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9968                                         }
9969                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9970                                 }
9971                         }
9972                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9973                         rsurface.vertex3f_bufferobject = 0;
9974                         rsurface.vertex3f_bufferoffset = 0;
9975                         break;
9976                 case Q3DEFORM_BULGE:
9977                         // deform vertex array to make the surface have moving bulges
9978                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9979                         {
9980                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9981                                 for (j = 0;j < surface->num_vertices;j++)
9982                                 {
9983                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
9984                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9985                                 }
9986                         }
9987                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9988                         rsurface.vertex3f_bufferobject = 0;
9989                         rsurface.vertex3f_bufferoffset = 0;
9990                         break;
9991                 case Q3DEFORM_MOVE:
9992                         // deform vertex array
9993                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9994                         VectorScale(deform->parms, scale, waveparms);
9995                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9996                         {
9997                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9998                                 for (j = 0;j < surface->num_vertices;j++)
9999                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
10000                         }
10001                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
10002                         rsurface.vertex3f_bufferobject = 0;
10003                         rsurface.vertex3f_bufferoffset = 0;
10004                         break;
10005                 }
10006         }
10007         // generate texcoords based on the chosen texcoord source
10008         switch(rsurface.texture->tcgen.tcgen)
10009         {
10010         default:
10011         case Q3TCGEN_TEXTURE:
10012                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
10013                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
10014                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
10015                 break;
10016         case Q3TCGEN_LIGHTMAP:
10017                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
10018                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
10019                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
10020                 break;
10021         case Q3TCGEN_VECTOR:
10022                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10023                 {
10024                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10025                         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)
10026                         {
10027                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
10028                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
10029                         }
10030                 }
10031                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
10032                 rsurface.texcoordtexture2f_bufferobject  = 0;
10033                 rsurface.texcoordtexture2f_bufferoffset  = 0;
10034                 break;
10035         case Q3TCGEN_ENVIRONMENT:
10036                 // make environment reflections using a spheremap
10037                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10038                 {
10039                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10040                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
10041                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
10042                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
10043                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
10044                         {
10045                                 // identical to Q3A's method, but executed in worldspace so
10046                                 // carried models can be shiny too
10047
10048                                 float viewer[3], d, reflected[3], worldreflected[3];
10049
10050                                 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
10051                                 // VectorNormalize(viewer);
10052
10053                                 d = DotProduct(normal, viewer);
10054
10055                                 reflected[0] = normal[0]*2*d - viewer[0];
10056                                 reflected[1] = normal[1]*2*d - viewer[1];
10057                                 reflected[2] = normal[2]*2*d - viewer[2];
10058                                 // note: this is proportinal to viewer, so we can normalize later
10059
10060                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10061                                 VectorNormalize(worldreflected);
10062
10063                                 // note: this sphere map only uses world x and z!
10064                                 // so positive and negative y will LOOK THE SAME.
10065                                 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
10066                                 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
10067                         }
10068                 }
10069                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
10070                 rsurface.texcoordtexture2f_bufferobject  = 0;
10071                 rsurface.texcoordtexture2f_bufferoffset  = 0;
10072                 break;
10073         }
10074         // the only tcmod that needs software vertex processing is turbulent, so
10075         // check for it here and apply the changes if needed
10076         // and we only support that as the first one
10077         // (handling a mixture of turbulent and other tcmods would be problematic
10078         //  without punting it entirely to a software path)
10079         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10080         {
10081                 amplitude = rsurface.texture->tcmods[0].parms[1];
10082                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
10083                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10084                 {
10085                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10086                         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)
10087                         {
10088                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10089                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10090                         }
10091                 }
10092                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
10093                 rsurface.texcoordtexture2f_bufferobject  = 0;
10094                 rsurface.texcoordtexture2f_bufferoffset  = 0;
10095         }
10096         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
10097         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
10098         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
10099         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
10100 }
10101
10102 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10103 {
10104         int i, j;
10105         const msurface_t *surface = texturesurfacelist[0];
10106         const msurface_t *surface2;
10107         int firstvertex;
10108         int endvertex;
10109         int numvertices;
10110         int numtriangles;
10111         // TODO: lock all array ranges before render, rather than on each surface
10112         if (texturenumsurfaces == 1)
10113                 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);
10114         else if (r_batchmode.integer == 2)
10115         {
10116                 #define MAXBATCHTRIANGLES 4096
10117                 int batchtriangles = 0;
10118                 static int batchelements[MAXBATCHTRIANGLES*3];
10119                 for (i = 0;i < texturenumsurfaces;i = j)
10120                 {
10121                         surface = texturesurfacelist[i];
10122                         j = i + 1;
10123                         if (surface->num_triangles > MAXBATCHTRIANGLES)
10124                         {
10125                                 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);
10126                                 continue;
10127                         }
10128                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
10129                         batchtriangles = surface->num_triangles;
10130                         firstvertex = surface->num_firstvertex;
10131                         endvertex = surface->num_firstvertex + surface->num_vertices;
10132                         for (;j < texturenumsurfaces;j++)
10133                         {
10134                                 surface2 = texturesurfacelist[j];
10135                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
10136                                         break;
10137                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
10138                                 batchtriangles += surface2->num_triangles;
10139                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
10140                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
10141                         }
10142                         surface2 = texturesurfacelist[j-1];
10143                         numvertices = endvertex - firstvertex;
10144                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
10145                 }
10146         }
10147         else if (r_batchmode.integer == 1)
10148         {
10149                 for (i = 0;i < texturenumsurfaces;i = j)
10150                 {
10151                         surface = texturesurfacelist[i];
10152                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10153                                 if (texturesurfacelist[j] != surface2)
10154                                         break;
10155                         surface2 = texturesurfacelist[j-1];
10156                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
10157                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
10158                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10159                 }
10160         }
10161         else
10162         {
10163                 for (i = 0;i < texturenumsurfaces;i++)
10164                 {
10165                         surface = texturesurfacelist[i];
10166                         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);
10167                 }
10168         }
10169 }
10170
10171 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
10172 {
10173         switch(vid.renderpath)
10174         {
10175         case RENDERPATH_CGGL:
10176 #ifdef SUPPORTCG
10177                 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
10178                 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
10179 #endif
10180                 break;
10181         case RENDERPATH_GL20:
10182                 if (r_glsl_permutation->loc_Texture_Lightmap  >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
10183                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
10184                 break;
10185         case RENDERPATH_GL13:
10186         case RENDERPATH_GL11:
10187                 R_Mesh_TexBind(0, surface->lightmaptexture);
10188                 break;
10189         }
10190 }
10191
10192 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
10193 {
10194         // pick the closest matching water plane and bind textures
10195         int planeindex, vertexindex;
10196         float d, bestd;
10197         vec3_t vert;
10198         const float *v;
10199         r_waterstate_waterplane_t *p, *bestp;
10200         bestd = 0;
10201         bestp = NULL;
10202         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
10203         {
10204                 d = 0;
10205                 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
10206                 {
10207                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10208                         d += fabs(PlaneDiff(vert, &p->plane));
10209                 }
10210                 if (bestd > d || !bestp)
10211                 {
10212                         bestd = d;
10213                         bestp = p;
10214                 }
10215         }
10216         switch(vid.renderpath)
10217         {
10218         case RENDERPATH_CGGL:
10219 #ifdef SUPPORTCG
10220                 if (r_cg_permutation->fp_Texture_Refraction) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR
10221                 if (r_cg_permutation->fp_Texture_Reflection) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR
10222 #endif
10223                 break;
10224         case RENDERPATH_GL20:
10225                 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
10226                 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
10227                 break;
10228         case RENDERPATH_GL13:
10229         case RENDERPATH_GL11:
10230                 break;
10231         }
10232 }
10233
10234 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10235 {
10236         int i;
10237         const msurface_t *surface;
10238         if (r_waterstate.renderingscene)
10239                 return;
10240         for (i = 0;i < texturenumsurfaces;i++)
10241         {
10242                 surface = texturesurfacelist[i];
10243                 RSurf_BindLightmapForSurface(surface);
10244                 RSurf_BindReflectionForSurface(surface);
10245                 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);
10246         }
10247 }
10248
10249 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10250 {
10251         int i;
10252         int j;
10253         const msurface_t *surface = texturesurfacelist[0];
10254         const msurface_t *surface2;
10255         int firstvertex;
10256         int endvertex;
10257         int numvertices;
10258         int numtriangles;
10259         if (texturenumsurfaces == 1)
10260         {
10261                 RSurf_BindLightmapForSurface(surface);
10262                 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);
10263         }
10264         else if (r_batchmode.integer == 2)
10265         {
10266 #define MAXBATCHTRIANGLES 4096
10267                 int batchtriangles = 0;
10268                 static int batchelements[MAXBATCHTRIANGLES*3];
10269                 for (i = 0;i < texturenumsurfaces;i = j)
10270                 {
10271                         surface = texturesurfacelist[i];
10272                         RSurf_BindLightmapForSurface(surface);
10273                         j = i + 1;
10274                         if (surface->num_triangles > MAXBATCHTRIANGLES)
10275                         {
10276                                 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);
10277                                 continue;
10278                         }
10279                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
10280                         batchtriangles = surface->num_triangles;
10281                         firstvertex = surface->num_firstvertex;
10282                         endvertex = surface->num_firstvertex + surface->num_vertices;
10283                         for (;j < texturenumsurfaces;j++)
10284                         {
10285                                 surface2 = texturesurfacelist[j];
10286                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
10287                                         break;
10288                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
10289                                 batchtriangles += surface2->num_triangles;
10290                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
10291                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
10292                         }
10293                         surface2 = texturesurfacelist[j-1];
10294                         numvertices = endvertex - firstvertex;
10295                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
10296                 }
10297         }
10298         else if (r_batchmode.integer == 1)
10299         {
10300 #if 0
10301                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
10302                 for (i = 0;i < texturenumsurfaces;i = j)
10303                 {
10304                         surface = texturesurfacelist[i];
10305                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10306                                 if (texturesurfacelist[j] != surface2)
10307                                         break;
10308                         Con_Printf(" %i", j - i);
10309                 }
10310                 Con_Printf("\n");
10311                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
10312 #endif
10313                 for (i = 0;i < texturenumsurfaces;i = j)
10314                 {
10315                         surface = texturesurfacelist[i];
10316                         RSurf_BindLightmapForSurface(surface);
10317                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10318                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
10319                                         break;
10320 #if 0
10321                         Con_Printf(" %i", j - i);
10322 #endif
10323                         surface2 = texturesurfacelist[j-1];
10324                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
10325                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
10326                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10327                 }
10328 #if 0
10329                 Con_Printf("\n");
10330 #endif
10331         }
10332         else
10333         {
10334                 for (i = 0;i < texturenumsurfaces;i++)
10335                 {
10336                         surface = texturesurfacelist[i];
10337                         RSurf_BindLightmapForSurface(surface);
10338                         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);
10339                 }
10340         }
10341 }
10342
10343 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10344 {
10345         int j;
10346         int texturesurfaceindex;
10347         if (r_showsurfaces.integer == 2)
10348         {
10349                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10350                 {
10351                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10352                         for (j = 0;j < surface->num_triangles;j++)
10353                         {
10354                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
10355                                 GL_Color(f, f, f, 1);
10356                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10357                         }
10358                 }
10359         }
10360         else
10361         {
10362                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10363                 {
10364                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10365                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
10366                         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);
10367                         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);
10368                 }
10369         }
10370 }
10371
10372 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10373 {
10374         int texturesurfaceindex;
10375         int i;
10376         const float *v;
10377         float *c2;
10378         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10379         {
10380                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10381                 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)
10382                 {
10383                         c2[0] = 0.5;
10384                         c2[1] = 0.5;
10385                         c2[2] = 0.5;
10386                         c2[3] = 1;
10387                 }
10388         }
10389         rsurface.lightmapcolor4f = rsurface.array_color4f;
10390         rsurface.lightmapcolor4f_bufferobject = 0;
10391         rsurface.lightmapcolor4f_bufferoffset = 0;
10392 }
10393
10394 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10395 {
10396         int texturesurfaceindex;
10397         int i;
10398         float f;
10399         const float *v;
10400         const float *c;
10401         float *c2;
10402         if (rsurface.lightmapcolor4f)
10403         {
10404                 // generate color arrays for the surfaces in this list
10405                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10406                 {
10407                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10408                         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)
10409                         {
10410                                 f = RSurf_FogVertex(v);
10411                                 c2[0] = c[0] * f;
10412                                 c2[1] = c[1] * f;
10413                                 c2[2] = c[2] * f;
10414                                 c2[3] = c[3];
10415                         }
10416                 }
10417         }
10418         else
10419         {
10420                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10421                 {
10422                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10423                         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)
10424                         {
10425                                 f = RSurf_FogVertex(v);
10426                                 c2[0] = f;
10427                                 c2[1] = f;
10428                                 c2[2] = f;
10429                                 c2[3] = 1;
10430                         }
10431                 }
10432         }
10433         rsurface.lightmapcolor4f = rsurface.array_color4f;
10434         rsurface.lightmapcolor4f_bufferobject = 0;
10435         rsurface.lightmapcolor4f_bufferoffset = 0;
10436 }
10437
10438 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10439 {
10440         int texturesurfaceindex;
10441         int i;
10442         float f;
10443         const float *v;
10444         const float *c;
10445         float *c2;
10446         if (!rsurface.lightmapcolor4f)
10447                 return;
10448         // generate color arrays for the surfaces in this list
10449         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10450         {
10451                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10452                 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)
10453                 {
10454                         f = RSurf_FogVertex(v);
10455                         c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10456                         c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10457                         c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10458                         c2[3] = c[3];
10459                 }
10460         }
10461         rsurface.lightmapcolor4f = rsurface.array_color4f;
10462         rsurface.lightmapcolor4f_bufferobject = 0;
10463         rsurface.lightmapcolor4f_bufferoffset = 0;
10464 }
10465
10466 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
10467 {
10468         int texturesurfaceindex;
10469         int i;
10470         const float *c;
10471         float *c2;
10472         if (!rsurface.lightmapcolor4f)
10473                 return;
10474         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10475         {
10476                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10477                 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)
10478                 {
10479                         c2[0] = c[0] * r;
10480                         c2[1] = c[1] * g;
10481                         c2[2] = c[2] * b;
10482                         c2[3] = c[3] * a;
10483                 }
10484         }
10485         rsurface.lightmapcolor4f = rsurface.array_color4f;
10486         rsurface.lightmapcolor4f_bufferobject = 0;
10487         rsurface.lightmapcolor4f_bufferoffset = 0;
10488 }
10489
10490 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10491 {
10492         int texturesurfaceindex;
10493         int i;
10494         const float *c;
10495         float *c2;
10496         if (!rsurface.lightmapcolor4f)
10497                 return;
10498         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10499         {
10500                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10501                 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)
10502                 {
10503                         c2[0] = c[0] + r_refdef.scene.ambient;
10504                         c2[1] = c[1] + r_refdef.scene.ambient;
10505                         c2[2] = c[2] + r_refdef.scene.ambient;
10506                         c2[3] = c[3];
10507                 }
10508         }
10509         rsurface.lightmapcolor4f = rsurface.array_color4f;
10510         rsurface.lightmapcolor4f_bufferobject = 0;
10511         rsurface.lightmapcolor4f_bufferoffset = 0;
10512 }
10513
10514 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10515 {
10516         // TODO: optimize
10517         rsurface.lightmapcolor4f = NULL;
10518         rsurface.lightmapcolor4f_bufferobject = 0;
10519         rsurface.lightmapcolor4f_bufferoffset = 0;
10520         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10521         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10522         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10523         GL_Color(r, g, b, a);
10524         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10525 }
10526
10527 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10528 {
10529         // TODO: optimize applyfog && applycolor case
10530         // just apply fog if necessary, and tint the fog color array if necessary
10531         rsurface.lightmapcolor4f = NULL;
10532         rsurface.lightmapcolor4f_bufferobject = 0;
10533         rsurface.lightmapcolor4f_bufferoffset = 0;
10534         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10535         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10536         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10537         GL_Color(r, g, b, a);
10538         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10539 }
10540
10541 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10542 {
10543         int texturesurfaceindex;
10544         int i;
10545         float *c;
10546         // TODO: optimize
10547         if (texturesurfacelist[0]->lightmapinfo)
10548         {
10549                 // generate color arrays for the surfaces in this list
10550                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10551                 {
10552                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10553                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
10554                         {
10555                                 if (surface->lightmapinfo->samples)
10556                                 {
10557                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
10558                                         float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
10559                                         VectorScale(lm, scale, c);
10560                                         if (surface->lightmapinfo->styles[1] != 255)
10561                                         {
10562                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
10563                                                 lm += size3;
10564                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
10565                                                 VectorMA(c, scale, lm, c);
10566                                                 if (surface->lightmapinfo->styles[2] != 255)
10567                                                 {
10568                                                         lm += size3;
10569                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
10570                                                         VectorMA(c, scale, lm, c);
10571                                                         if (surface->lightmapinfo->styles[3] != 255)
10572                                                         {
10573                                                                 lm += size3;
10574                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
10575                                                                 VectorMA(c, scale, lm, c);
10576                                                         }
10577                                                 }
10578                                         }
10579                                 }
10580                                 else
10581                                         VectorClear(c);
10582                                 c[3] = 1;
10583                         }
10584                 }
10585                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10586                 rsurface.lightmapcolor4f_bufferobject = 0;
10587                 rsurface.lightmapcolor4f_bufferoffset = 0;
10588         }
10589         else
10590         {
10591                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10592                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10593                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10594         }
10595         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10596         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10597         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10598         GL_Color(r, g, b, a);
10599         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10600 }
10601
10602 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
10603 {
10604         int texturesurfaceindex;
10605         int i;
10606         float f;
10607         float alpha;
10608         const float *v;
10609         const float *n;
10610         float *c;
10611         vec3_t ambientcolor;
10612         vec3_t diffusecolor;
10613         vec3_t lightdir;
10614         // TODO: optimize
10615         // model lighting
10616         VectorCopy(rsurface.modellight_lightdir, lightdir);
10617         f = 0.5f * r_refdef.lightmapintensity;
10618         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10619         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10620         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10621         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10622         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10623         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10624         alpha = *a;
10625         if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
10626         {
10627                 // generate color arrays for the surfaces in this list
10628                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10629                 {
10630                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10631                         int numverts = surface->num_vertices;
10632                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
10633                         n = rsurface.normal3f + 3 * surface->num_firstvertex;
10634                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
10635                         // q3-style directional shading
10636                         for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
10637                         {
10638                                 if ((f = DotProduct(n, lightdir)) > 0)
10639                                         VectorMA(ambientcolor, f, diffusecolor, c);
10640                                 else
10641                                         VectorCopy(ambientcolor, c);
10642                                 c[3] = alpha;
10643                         }
10644                 }
10645                 *r = 1;
10646                 *g = 1;
10647                 *b = 1;
10648                 *a = 1;
10649                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10650                 rsurface.lightmapcolor4f_bufferobject = 0;
10651                 rsurface.lightmapcolor4f_bufferoffset = 0;
10652                 *applycolor = false;
10653         }
10654         else
10655         {
10656                 *r = ambientcolor[0];
10657                 *g = ambientcolor[1];
10658                 *b = ambientcolor[2];
10659                 rsurface.lightmapcolor4f = NULL;
10660                 rsurface.lightmapcolor4f_bufferobject = 0;
10661                 rsurface.lightmapcolor4f_bufferoffset = 0;
10662         }
10663 }
10664
10665 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10666 {
10667         RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
10668         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10669         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10670         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10671         GL_Color(r, g, b, a);
10672         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10673 }
10674
10675 void RSurf_SetupDepthAndCulling(void)
10676 {
10677         // submodels are biased to avoid z-fighting with world surfaces that they
10678         // may be exactly overlapping (avoids z-fighting artifacts on certain
10679         // doors and things in Quake maps)
10680         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10681         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10682         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10683         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10684 }
10685
10686 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10687 {
10688         // transparent sky would be ridiculous
10689         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10690                 return;
10691         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10692         skyrenderlater = true;
10693         RSurf_SetupDepthAndCulling();
10694         GL_DepthMask(true);
10695         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10696         // skymasking on them, and Quake3 never did sky masking (unlike
10697         // software Quake and software Quake2), so disable the sky masking
10698         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10699         // and skymasking also looks very bad when noclipping outside the
10700         // level, so don't use it then either.
10701         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
10702         {
10703                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10704                 R_Mesh_ColorPointer(NULL, 0, 0);
10705                 R_Mesh_ResetTextureState();
10706                 if (skyrendermasked)
10707                 {
10708                         R_SetupShader_DepthOrShadow();
10709                         // depth-only (masking)
10710                         GL_ColorMask(0,0,0,0);
10711                         // just to make sure that braindead drivers don't draw
10712                         // anything despite that colormask...
10713                         GL_BlendFunc(GL_ZERO, GL_ONE);
10714                 }
10715                 else
10716                 {
10717                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10718                         // fog sky
10719                         GL_BlendFunc(GL_ONE, GL_ZERO);
10720                 }
10721                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10722                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10723                 if (skyrendermasked)
10724                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10725         }
10726         R_Mesh_ResetTextureState();
10727         GL_Color(1, 1, 1, 1);
10728 }
10729
10730 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10731 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10732 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10733 {
10734         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
10735                 return;
10736         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10737         if (prepass)
10738         {
10739                 // render screenspace normalmap to texture
10740                 GL_DepthMask(true);
10741                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY);
10742                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10743         }
10744         else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !r_waterstate.renderingscene)
10745         {
10746                 // render water or distortion background, then blend surface on top
10747                 GL_DepthMask(true);
10748                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
10749                 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10750                 GL_DepthMask(false);
10751                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
10752                 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10753                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10754                 else
10755                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10756         }
10757         else
10758         {
10759                 // render surface normally
10760                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10761                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
10762                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
10763                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10764                 else if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10765                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10766                 else
10767                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10768         }
10769 }
10770
10771 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10772 {
10773         // OpenGL 1.3 path - anything not completely ancient
10774         int texturesurfaceindex;
10775         qboolean applycolor;
10776         qboolean applyfog;
10777         int layerindex;
10778         const texturelayer_t *layer;
10779         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10780
10781         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10782         {
10783                 vec4_t layercolor;
10784                 int layertexrgbscale;
10785                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10786                 {
10787                         if (layerindex == 0)
10788                                 GL_AlphaTest(true);
10789                         else
10790                         {
10791                                 GL_AlphaTest(false);
10792                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10793                         }
10794                 }
10795                 GL_DepthMask(layer->depthmask && writedepth);
10796                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10797                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10798                 {
10799                         layertexrgbscale = 4;
10800                         VectorScale(layer->color, 0.25f, layercolor);
10801                 }
10802                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10803                 {
10804                         layertexrgbscale = 2;
10805                         VectorScale(layer->color, 0.5f, layercolor);
10806                 }
10807                 else
10808                 {
10809                         layertexrgbscale = 1;
10810                         VectorScale(layer->color, 1.0f, layercolor);
10811                 }
10812                 layercolor[3] = layer->color[3];
10813                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10814                 R_Mesh_ColorPointer(NULL, 0, 0);
10815                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10816                 switch (layer->type)
10817                 {
10818                 case TEXTURELAYERTYPE_LITTEXTURE:
10819                         // single-pass lightmapped texture with 2x rgbscale
10820                         R_Mesh_TexBind(0, r_texture_white);
10821                         R_Mesh_TexMatrix(0, NULL);
10822                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10823                         R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10824                         R_Mesh_TexBind(1, layer->texture);
10825                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10826                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10827                         R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10828                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10829                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10830                         else if (rsurface.uselightmaptexture)
10831                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10832                         else
10833                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10834                         break;
10835                 case TEXTURELAYERTYPE_TEXTURE:
10836                         // singletexture unlit texture with transparency support
10837                         R_Mesh_TexBind(0, layer->texture);
10838                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10839                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10840                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10841                         R_Mesh_TexBind(1, 0);
10842                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10843                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10844                         break;
10845                 case TEXTURELAYERTYPE_FOG:
10846                         // singletexture fogging
10847                         if (layer->texture)
10848                         {
10849                                 R_Mesh_TexBind(0, layer->texture);
10850                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10851                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10852                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10853                         }
10854                         else
10855                         {
10856                                 R_Mesh_TexBind(0, 0);
10857                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10858                         }
10859                         R_Mesh_TexBind(1, 0);
10860                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10861                         // generate a color array for the fog pass
10862                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10863                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10864                         {
10865                                 int i;
10866                                 float f;
10867                                 const float *v;
10868                                 float *c;
10869                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10870                                 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)
10871                                 {
10872                                         f = 1 - RSurf_FogVertex(v);
10873                                         c[0] = layercolor[0];
10874                                         c[1] = layercolor[1];
10875                                         c[2] = layercolor[2];
10876                                         c[3] = f * layercolor[3];
10877                                 }
10878                         }
10879                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10880                         break;
10881                 default:
10882                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10883                 }
10884         }
10885         CHECKGLERROR
10886         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10887         {
10888                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10889                 GL_AlphaTest(false);
10890         }
10891 }
10892
10893 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10894 {
10895         // OpenGL 1.1 - crusty old voodoo path
10896         int texturesurfaceindex;
10897         qboolean applyfog;
10898         int layerindex;
10899         const texturelayer_t *layer;
10900         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10901
10902         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10903         {
10904                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10905                 {
10906                         if (layerindex == 0)
10907                                 GL_AlphaTest(true);
10908                         else
10909                         {
10910                                 GL_AlphaTest(false);
10911                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10912                         }
10913                 }
10914                 GL_DepthMask(layer->depthmask && writedepth);
10915                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10916                 R_Mesh_ColorPointer(NULL, 0, 0);
10917                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10918                 switch (layer->type)
10919                 {
10920                 case TEXTURELAYERTYPE_LITTEXTURE:
10921                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10922                         {
10923                                 // two-pass lit texture with 2x rgbscale
10924                                 // first the lightmap pass
10925                                 R_Mesh_TexBind(0, r_texture_white);
10926                                 R_Mesh_TexMatrix(0, NULL);
10927                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10928                                 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10929                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10930                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10931                                 else if (rsurface.uselightmaptexture)
10932                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10933                                 else
10934                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10935                                 // then apply the texture to it
10936                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10937                                 R_Mesh_TexBind(0, layer->texture);
10938                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10939                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10940                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10941                                 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);
10942                         }
10943                         else
10944                         {
10945                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10946                                 R_Mesh_TexBind(0, layer->texture);
10947                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10948                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10949                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10950                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10951                                         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);
10952                                 else
10953                                         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);
10954                         }
10955                         break;
10956                 case TEXTURELAYERTYPE_TEXTURE:
10957                         // singletexture unlit texture with transparency support
10958                         R_Mesh_TexBind(0, layer->texture);
10959                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10960                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10961                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10962                         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);
10963                         break;
10964                 case TEXTURELAYERTYPE_FOG:
10965                         // singletexture fogging
10966                         if (layer->texture)
10967                         {
10968                                 R_Mesh_TexBind(0, layer->texture);
10969                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10970                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10971                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10972                         }
10973                         else
10974                         {
10975                                 R_Mesh_TexBind(0, 0);
10976                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10977                         }
10978                         // generate a color array for the fog pass
10979                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10980                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10981                         {
10982                                 int i;
10983                                 float f;
10984                                 const float *v;
10985                                 float *c;
10986                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10987                                 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)
10988                                 {
10989                                         f = 1 - RSurf_FogVertex(v);
10990                                         c[0] = layer->color[0];
10991                                         c[1] = layer->color[1];
10992                                         c[2] = layer->color[2];
10993                                         c[3] = f * layer->color[3];
10994                                 }
10995                         }
10996                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10997                         break;
10998                 default:
10999                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11000                 }
11001         }
11002         CHECKGLERROR
11003         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11004         {
11005                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
11006                 GL_AlphaTest(false);
11007         }
11008 }
11009
11010 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11011 {
11012         float c[4];
11013
11014         GL_AlphaTest(false);
11015         R_Mesh_ColorPointer(NULL, 0, 0);
11016         R_Mesh_ResetTextureState();
11017         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11018
11019         if(rsurface.texture && rsurface.texture->currentskinframe)
11020         {
11021                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11022                 c[3] *= rsurface.texture->currentalpha;
11023         }
11024         else
11025         {
11026                 c[0] = 1;
11027                 c[1] = 0;
11028                 c[2] = 1;
11029                 c[3] = 1;
11030         }
11031
11032         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11033         {
11034                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11035                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11036                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11037         }
11038
11039         // brighten it up (as texture value 127 means "unlit")
11040         c[0] *= 2 * r_refdef.view.colorscale;
11041         c[1] *= 2 * r_refdef.view.colorscale;
11042         c[2] *= 2 * r_refdef.view.colorscale;
11043
11044         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11045                 c[3] *= r_wateralpha.value;
11046
11047         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11048         {
11049                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11050                 GL_DepthMask(false);
11051         }
11052         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11053         {
11054                 GL_BlendFunc(GL_ONE, GL_ONE);
11055                 GL_DepthMask(false);
11056         }
11057         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11058         {
11059                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11060                 GL_DepthMask(false);
11061         }
11062         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11063         {
11064                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11065                 GL_DepthMask(false);
11066         }
11067         else
11068         {
11069                 GL_BlendFunc(GL_ONE, GL_ZERO);
11070                 GL_DepthMask(writedepth);
11071         }
11072
11073         rsurface.lightmapcolor4f = NULL;
11074
11075         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11076         {
11077                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11078
11079                 rsurface.lightmapcolor4f = NULL;
11080                 rsurface.lightmapcolor4f_bufferobject = 0;
11081                 rsurface.lightmapcolor4f_bufferoffset = 0;
11082         }
11083         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11084         {
11085                 qboolean applycolor = true;
11086                 float one = 1.0;
11087
11088                 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
11089
11090                 r_refdef.lightmapintensity = 1;
11091                 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
11092                 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11093         }
11094         else
11095         {
11096                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11097
11098                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
11099                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
11100                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11101         }
11102
11103         if(!rsurface.lightmapcolor4f)
11104                 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
11105
11106         RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
11107         RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
11108         if(r_refdef.fogenabled)
11109                 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
11110
11111         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
11112         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11113 }
11114
11115 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11116 {
11117         CHECKGLERROR
11118         RSurf_SetupDepthAndCulling();
11119         if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
11120         {
11121                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
11122                 return;
11123         }
11124         switch (vid.renderpath)
11125         {
11126         case RENDERPATH_GL20:
11127         case RENDERPATH_CGGL:
11128                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11129                 break;
11130         case RENDERPATH_GL13:
11131                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11132                 break;
11133         case RENDERPATH_GL11:
11134                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11135                 break;
11136         }
11137         CHECKGLERROR
11138 }
11139
11140 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11141 {
11142         CHECKGLERROR
11143         RSurf_SetupDepthAndCulling();
11144         if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
11145         {
11146                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
11147                 return;
11148         }
11149         switch (vid.renderpath)
11150         {
11151         case RENDERPATH_GL20:
11152         case RENDERPATH_CGGL:
11153                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11154                 break;
11155         case RENDERPATH_GL13:
11156                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11157                 break;
11158         case RENDERPATH_GL11:
11159                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11160                 break;
11161         }
11162         CHECKGLERROR
11163 }
11164
11165 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11166 {
11167         int i, j;
11168         int texturenumsurfaces, endsurface;
11169         texture_t *texture;
11170         const msurface_t *surface;
11171         const msurface_t *texturesurfacelist[256];
11172
11173         // if the model is static it doesn't matter what value we give for
11174         // wantnormals and wanttangents, so this logic uses only rules applicable
11175         // to a model, knowing that they are meaningless otherwise
11176         if (ent == r_refdef.scene.worldentity)
11177                 RSurf_ActiveWorldEntity();
11178         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11179                 RSurf_ActiveModelEntity(ent, false, false, false);
11180         else
11181         {
11182                 switch (vid.renderpath)
11183                 {
11184                 case RENDERPATH_GL20:
11185                 case RENDERPATH_CGGL:
11186                         RSurf_ActiveModelEntity(ent, true, true, false);
11187                         break;
11188                 case RENDERPATH_GL13:
11189                 case RENDERPATH_GL11:
11190                         RSurf_ActiveModelEntity(ent, true, false, false);
11191                         break;
11192                 }
11193         }
11194
11195         if (r_transparentdepthmasking.integer)
11196         {
11197                 qboolean setup = false;
11198                 for (i = 0;i < numsurfaces;i = j)
11199                 {
11200                         j = i + 1;
11201                         surface = rsurface.modelsurfaces + surfacelist[i];
11202                         texture = surface->texture;
11203                         rsurface.texture = R_GetCurrentTexture(texture);
11204                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11205                         // scan ahead until we find a different texture
11206                         endsurface = min(i + 1024, numsurfaces);
11207                         texturenumsurfaces = 0;
11208                         texturesurfacelist[texturenumsurfaces++] = surface;
11209                         for (;j < endsurface;j++)
11210                         {
11211                                 surface = rsurface.modelsurfaces + surfacelist[j];
11212                                 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
11213                                         break;
11214                                 texturesurfacelist[texturenumsurfaces++] = surface;
11215                         }
11216                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11217                                 continue;
11218                         // render the range of surfaces as depth
11219                         if (!setup)
11220                         {
11221                                 setup = true;
11222                                 GL_ColorMask(0,0,0,0);
11223                                 GL_Color(1,1,1,1);
11224                                 GL_DepthTest(true);
11225                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11226                                 GL_DepthMask(true);
11227                                 GL_AlphaTest(false);
11228                                 R_Mesh_ColorPointer(NULL, 0, 0);
11229                                 R_Mesh_ResetTextureState();
11230                                 R_SetupShader_DepthOrShadow();
11231                         }
11232                         RSurf_SetupDepthAndCulling();
11233                         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11234                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11235                 }
11236                 if (setup)
11237                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11238         }
11239
11240         for (i = 0;i < numsurfaces;i = j)
11241         {
11242                 j = i + 1;
11243                 surface = rsurface.modelsurfaces + surfacelist[i];
11244                 texture = surface->texture;
11245                 rsurface.texture = R_GetCurrentTexture(texture);
11246                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11247                 // scan ahead until we find a different texture
11248                 endsurface = min(i + 1024, numsurfaces);
11249                 texturenumsurfaces = 0;
11250                 texturesurfacelist[texturenumsurfaces++] = surface;
11251                 for (;j < endsurface;j++)
11252                 {
11253                         surface = rsurface.modelsurfaces + surfacelist[j];
11254                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
11255                                 break;
11256                         texturesurfacelist[texturenumsurfaces++] = surface;
11257                 }
11258                 // render the range of surfaces
11259                 if (ent == r_refdef.scene.worldentity)
11260                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11261                 else
11262                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11263         }
11264         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11265         GL_AlphaTest(false);
11266 }
11267
11268 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
11269 {
11270         // transparent surfaces get pushed off into the transparent queue
11271         int surfacelistindex;
11272         const msurface_t *surface;
11273         vec3_t tempcenter, center;
11274         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11275         {
11276                 surface = texturesurfacelist[surfacelistindex];
11277                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11278                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11279                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11280                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11281                 if (queueentity->transparent_offset) // transparent offset
11282                 {
11283                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
11284                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
11285                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
11286                 }
11287                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
11288         }
11289 }
11290
11291 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11292 {
11293         const entity_render_t *queueentity = r_refdef.scene.worldentity;
11294         CHECKGLERROR
11295         if (depthonly)
11296         {
11297                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11298                         return;
11299                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11300                         return;
11301                 RSurf_SetupDepthAndCulling();
11302                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11303                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11304         }
11305         else if (prepass)
11306         {
11307                 if (!rsurface.texture->currentnumlayers)
11308                         return;
11309                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11310                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11311                 else
11312                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11313         }
11314         else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
11315         {
11316                 RSurf_SetupDepthAndCulling();
11317                 GL_AlphaTest(false);
11318                 R_Mesh_ColorPointer(NULL, 0, 0);
11319                 R_Mesh_ResetTextureState();
11320                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11321                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11322                 GL_DepthMask(true);
11323                 GL_BlendFunc(GL_ONE, GL_ZERO);
11324                 GL_Color(0, 0, 0, 1);
11325                 GL_DepthTest(writedepth);
11326                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11327         }
11328         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
11329         {
11330                 RSurf_SetupDepthAndCulling();
11331                 GL_AlphaTest(false);
11332                 R_Mesh_ColorPointer(NULL, 0, 0);
11333                 R_Mesh_ResetTextureState();
11334                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11335                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11336                 GL_DepthMask(true);
11337                 GL_BlendFunc(GL_ONE, GL_ZERO);
11338                 GL_DepthTest(true);
11339                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11340         }
11341         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11342                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11343         else if (!rsurface.texture->currentnumlayers)
11344                 return;
11345         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11346         {
11347                 // in the deferred case, transparent surfaces were queued during prepass
11348                 if (!r_shadow_usingdeferredprepass)
11349                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11350         }
11351         else
11352         {
11353                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11354                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11355         }
11356         CHECKGLERROR
11357 }
11358
11359 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11360 {
11361         int i, j;
11362         texture_t *texture;
11363         // break the surface list down into batches by texture and use of lightmapping
11364         for (i = 0;i < numsurfaces;i = j)
11365         {
11366                 j = i + 1;
11367                 // texture is the base texture pointer, rsurface.texture is the
11368                 // current frame/skin the texture is directing us to use (for example
11369                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11370                 // use skin 1 instead)
11371                 texture = surfacelist[i]->texture;
11372                 rsurface.texture = R_GetCurrentTexture(texture);
11373                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11374                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11375                 {
11376                         // if this texture is not the kind we want, skip ahead to the next one
11377                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11378                                 ;
11379                         continue;
11380                 }
11381                 // simply scan ahead until we find a different texture or lightmap state
11382                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11383                         ;
11384                 // render the range of surfaces
11385                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11386         }
11387 }
11388
11389 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
11390 {
11391         CHECKGLERROR
11392         if (depthonly)
11393         {
11394                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11395                         return;
11396                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11397                         return;
11398                 RSurf_SetupDepthAndCulling();
11399                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11400                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11401         }
11402         else if (prepass)
11403         {
11404                 if (!rsurface.texture->currentnumlayers)
11405                         return;
11406                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11407                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11408                 else
11409                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11410         }
11411         else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
11412         {
11413                 RSurf_SetupDepthAndCulling();
11414                 GL_AlphaTest(false);
11415                 R_Mesh_ColorPointer(NULL, 0, 0);
11416                 R_Mesh_ResetTextureState();
11417                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11418                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11419                 GL_DepthMask(true);
11420                 GL_BlendFunc(GL_ONE, GL_ZERO);
11421                 GL_Color(0, 0, 0, 1);
11422                 GL_DepthTest(writedepth);
11423                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11424         }
11425         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11426         {
11427                 RSurf_SetupDepthAndCulling();
11428                 GL_AlphaTest(false);
11429                 R_Mesh_ColorPointer(NULL, 0, 0);
11430                 R_Mesh_ResetTextureState();
11431                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11432                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11433                 GL_DepthMask(true);
11434                 GL_BlendFunc(GL_ONE, GL_ZERO);
11435                 GL_DepthTest(true);
11436                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11437         }
11438         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11439                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11440         else if (!rsurface.texture->currentnumlayers)
11441                 return;
11442         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11443         {
11444                 // in the deferred case, transparent surfaces were queued during prepass
11445                 if (!r_shadow_usingdeferredprepass)
11446                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11447         }
11448         else
11449         {
11450                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11451                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11452         }
11453         CHECKGLERROR
11454 }
11455
11456 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11457 {
11458         int i, j;
11459         texture_t *texture;
11460         // break the surface list down into batches by texture and use of lightmapping
11461         for (i = 0;i < numsurfaces;i = j)
11462         {
11463                 j = i + 1;
11464                 // texture is the base texture pointer, rsurface.texture is the
11465                 // current frame/skin the texture is directing us to use (for example
11466                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11467                 // use skin 1 instead)
11468                 texture = surfacelist[i]->texture;
11469                 rsurface.texture = R_GetCurrentTexture(texture);
11470                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11471                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11472                 {
11473                         // if this texture is not the kind we want, skip ahead to the next one
11474                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11475                                 ;
11476                         continue;
11477                 }
11478                 // simply scan ahead until we find a different texture or lightmap state
11479                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11480                         ;
11481                 // render the range of surfaces
11482                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
11483         }
11484 }
11485
11486 float locboxvertex3f[6*4*3] =
11487 {
11488         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11489         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11490         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11491         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11492         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11493         1,0,0, 0,0,0, 0,1,0, 1,1,0
11494 };
11495
11496 unsigned short locboxelements[6*2*3] =
11497 {
11498          0, 1, 2, 0, 2, 3,
11499          4, 5, 6, 4, 6, 7,
11500          8, 9,10, 8,10,11,
11501         12,13,14, 12,14,15,
11502         16,17,18, 16,18,19,
11503         20,21,22, 20,22,23
11504 };
11505
11506 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11507 {
11508         int i, j;
11509         cl_locnode_t *loc = (cl_locnode_t *)ent;
11510         vec3_t mins, size;
11511         float vertex3f[6*4*3];
11512         CHECKGLERROR
11513         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11514         GL_DepthMask(false);
11515         GL_DepthRange(0, 1);
11516         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11517         GL_DepthTest(true);
11518         GL_CullFace(GL_NONE);
11519         R_EntityMatrix(&identitymatrix);
11520
11521         R_Mesh_VertexPointer(vertex3f, 0, 0);
11522         R_Mesh_ColorPointer(NULL, 0, 0);
11523         R_Mesh_ResetTextureState();
11524         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11525
11526         i = surfacelist[0];
11527         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11528                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11529                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11530                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11531
11532         if (VectorCompare(loc->mins, loc->maxs))
11533         {
11534                 VectorSet(size, 2, 2, 2);
11535                 VectorMA(loc->mins, -0.5f, size, mins);
11536         }
11537         else
11538         {
11539                 VectorCopy(loc->mins, mins);
11540                 VectorSubtract(loc->maxs, loc->mins, size);
11541         }
11542
11543         for (i = 0;i < 6*4*3;)
11544                 for (j = 0;j < 3;j++, i++)
11545                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11546
11547         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
11548 }
11549
11550 void R_DrawLocs(void)
11551 {
11552         int index;
11553         cl_locnode_t *loc, *nearestloc;
11554         vec3_t center;
11555         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11556         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11557         {
11558                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11559                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11560         }
11561 }
11562
11563 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11564 {
11565         if (decalsystem->decals)
11566                 Mem_Free(decalsystem->decals);
11567         memset(decalsystem, 0, sizeof(*decalsystem));
11568 }
11569
11570 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)
11571 {
11572         tridecal_t *decal;
11573         tridecal_t *decals;
11574         int i;
11575
11576         // expand or initialize the system
11577         if (decalsystem->maxdecals <= decalsystem->numdecals)
11578         {
11579                 decalsystem_t old = *decalsystem;
11580                 qboolean useshortelements;
11581                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11582                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11583                 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)));
11584                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11585                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11586                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11587                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11588                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11589                 if (decalsystem->numdecals)
11590                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11591                 if (old.decals)
11592                         Mem_Free(old.decals);
11593                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11594                         decalsystem->element3i[i] = i;
11595                 if (useshortelements)
11596                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11597                                 decalsystem->element3s[i] = i;
11598         }
11599
11600         // grab a decal and search for another free slot for the next one
11601         decals = decalsystem->decals;
11602         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11603         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
11604                 ;
11605         decalsystem->freedecal = i;
11606         if (decalsystem->numdecals <= i)
11607                 decalsystem->numdecals = i + 1;
11608
11609         // initialize the decal
11610         decal->lived = 0;
11611         decal->triangleindex = triangleindex;
11612         decal->surfaceindex = surfaceindex;
11613         decal->decalsequence = decalsequence;
11614         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
11615         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
11616         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
11617         decal->color4ub[0][3] = 255;
11618         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
11619         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
11620         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
11621         decal->color4ub[1][3] = 255;
11622         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
11623         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
11624         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
11625         decal->color4ub[2][3] = 255;
11626         decal->vertex3f[0][0] = v0[0];
11627         decal->vertex3f[0][1] = v0[1];
11628         decal->vertex3f[0][2] = v0[2];
11629         decal->vertex3f[1][0] = v1[0];
11630         decal->vertex3f[1][1] = v1[1];
11631         decal->vertex3f[1][2] = v1[2];
11632         decal->vertex3f[2][0] = v2[0];
11633         decal->vertex3f[2][1] = v2[1];
11634         decal->vertex3f[2][2] = v2[2];
11635         decal->texcoord2f[0][0] = t0[0];
11636         decal->texcoord2f[0][1] = t0[1];
11637         decal->texcoord2f[1][0] = t1[0];
11638         decal->texcoord2f[1][1] = t1[1];
11639         decal->texcoord2f[2][0] = t2[0];
11640         decal->texcoord2f[2][1] = t2[1];
11641 }
11642
11643 extern cvar_t cl_decals_bias;
11644 extern cvar_t cl_decals_models;
11645 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11646 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)
11647 {
11648         matrix4x4_t projection;
11649         decalsystem_t *decalsystem;
11650         qboolean dynamic;
11651         dp_model_t *model;
11652         const float *vertex3f;
11653         const msurface_t *surface;
11654         const msurface_t *surfaces;
11655         const int *surfacelist;
11656         const texture_t *texture;
11657         int numtriangles;
11658         int numsurfacelist;
11659         int surfacelistindex;
11660         int surfaceindex;
11661         int triangleindex;
11662         int cornerindex;
11663         int index;
11664         int numpoints;
11665         const int *e;
11666         float localorigin[3];
11667         float localnormal[3];
11668         float localmins[3];
11669         float localmaxs[3];
11670         float localsize;
11671         float v[9][3];
11672         float tc[9][2];
11673         float c[9][4];
11674         //float normal[3];
11675         float planes[6][4];
11676         float f;
11677         float points[2][9][3];
11678         float angles[3];
11679         float temp[3];
11680
11681         decalsystem = &ent->decalsystem;
11682         model = ent->model;
11683         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11684         {
11685                 R_DecalSystem_Reset(&ent->decalsystem);
11686                 return;
11687         }
11688
11689         if (!model->brush.data_nodes && !cl_decals_models.integer)
11690         {
11691                 if (decalsystem->model)
11692                         R_DecalSystem_Reset(decalsystem);
11693                 return;
11694         }
11695
11696         if (decalsystem->model != model)
11697                 R_DecalSystem_Reset(decalsystem);
11698         decalsystem->model = model;
11699
11700         RSurf_ActiveModelEntity(ent, false, false, false);
11701
11702         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11703         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11704         VectorNormalize(localnormal);
11705         localsize = worldsize*rsurface.inversematrixscale;
11706         localmins[0] = localorigin[0] - localsize;
11707         localmins[1] = localorigin[1] - localsize;
11708         localmins[2] = localorigin[2] - localsize;
11709         localmaxs[0] = localorigin[0] + localsize;
11710         localmaxs[1] = localorigin[1] + localsize;
11711         localmaxs[2] = localorigin[2] + localsize;
11712
11713         //VectorCopy(localnormal, planes[4]);
11714         //VectorVectors(planes[4], planes[2], planes[0]);
11715         AnglesFromVectors(angles, localnormal, NULL, false);
11716         AngleVectors(angles, planes[0], planes[2], planes[4]);
11717         VectorNegate(planes[0], planes[1]);
11718         VectorNegate(planes[2], planes[3]);
11719         VectorNegate(planes[4], planes[5]);
11720         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11721         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11722         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11723         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11724         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11725         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11726
11727 #if 1
11728 // works
11729 {
11730         matrix4x4_t forwardprojection;
11731         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11732         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11733 }
11734 #else
11735 // broken
11736 {
11737         float projectionvector[4][3];
11738         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11739         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11740         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11741         projectionvector[0][0] = planes[0][0] * ilocalsize;
11742         projectionvector[0][1] = planes[1][0] * ilocalsize;
11743         projectionvector[0][2] = planes[2][0] * ilocalsize;
11744         projectionvector[1][0] = planes[0][1] * ilocalsize;
11745         projectionvector[1][1] = planes[1][1] * ilocalsize;
11746         projectionvector[1][2] = planes[2][1] * ilocalsize;
11747         projectionvector[2][0] = planes[0][2] * ilocalsize;
11748         projectionvector[2][1] = planes[1][2] * ilocalsize;
11749         projectionvector[2][2] = planes[2][2] * ilocalsize;
11750         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11751         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11752         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11753         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11754 }
11755 #endif
11756
11757         dynamic = model->surfmesh.isanimated;
11758         vertex3f = rsurface.modelvertex3f;
11759         numsurfacelist = model->nummodelsurfaces;
11760         surfacelist = model->sortedmodelsurfaces;
11761         surfaces = model->data_surfaces;
11762         for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11763         {
11764                 surfaceindex = surfacelist[surfacelistindex];
11765                 surface = surfaces + surfaceindex;
11766                 // check cull box first because it rejects more than any other check
11767                 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11768                         continue;
11769                 // skip transparent surfaces
11770                 texture = surface->texture;
11771                 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11772                         continue;
11773                 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11774                         continue;
11775                 numtriangles = surface->num_triangles;
11776                 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
11777                 {
11778                         for (cornerindex = 0;cornerindex < 3;cornerindex++)
11779                         {
11780                                 index = 3*e[cornerindex];
11781                                 VectorCopy(vertex3f + index, v[cornerindex]);
11782                         }
11783                         // cull backfaces
11784                         //TriangleNormal(v[0], v[1], v[2], normal);
11785                         //if (DotProduct(normal, localnormal) < 0.0f)
11786                         //      continue;
11787                         // clip by each of the box planes formed from the projection matrix
11788                         // if anything survives, we emit the decal
11789                         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]);
11790                         if (numpoints < 3)
11791                                 continue;
11792                         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]);
11793                         if (numpoints < 3)
11794                                 continue;
11795                         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]);
11796                         if (numpoints < 3)
11797                                 continue;
11798                         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]);
11799                         if (numpoints < 3)
11800                                 continue;
11801                         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]);
11802                         if (numpoints < 3)
11803                                 continue;
11804                         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]);
11805                         if (numpoints < 3)
11806                                 continue;
11807                         // some part of the triangle survived, so we have to accept it...
11808                         if (dynamic)
11809                         {
11810                                 // dynamic always uses the original triangle
11811                                 numpoints = 3;
11812                                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11813                                 {
11814                                         index = 3*e[cornerindex];
11815                                         VectorCopy(vertex3f + index, v[cornerindex]);
11816                                 }
11817                         }
11818                         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11819                         {
11820                                 // convert vertex positions to texcoords
11821                                 Matrix4x4_Transform(&projection, v[cornerindex], temp);
11822                                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11823                                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11824                                 // calculate distance fade from the projection origin
11825                                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11826                                 f = bound(0.0f, f, 1.0f);
11827                                 c[cornerindex][0] = r * f;
11828                                 c[cornerindex][1] = g * f;
11829                                 c[cornerindex][2] = b * f;
11830                                 c[cornerindex][3] = 1.0f;
11831                                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11832                         }
11833                         if (dynamic)
11834                                 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);
11835                         else
11836                                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11837                                         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);
11838                 }
11839         }
11840 }
11841
11842 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11843 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)
11844 {
11845         int renderentityindex;
11846         float worldmins[3];
11847         float worldmaxs[3];
11848         entity_render_t *ent;
11849
11850         if (!cl_decals_newsystem.integer)
11851                 return;
11852
11853         worldmins[0] = worldorigin[0] - worldsize;
11854         worldmins[1] = worldorigin[1] - worldsize;
11855         worldmins[2] = worldorigin[2] - worldsize;
11856         worldmaxs[0] = worldorigin[0] + worldsize;
11857         worldmaxs[1] = worldorigin[1] + worldsize;
11858         worldmaxs[2] = worldorigin[2] + worldsize;
11859
11860         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11861
11862         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11863         {
11864                 ent = r_refdef.scene.entities[renderentityindex];
11865                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11866                         continue;
11867
11868                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11869         }
11870 }
11871
11872 typedef struct r_decalsystem_splatqueue_s
11873 {
11874         vec3_t worldorigin;
11875         vec3_t worldnormal;
11876         float color[4];
11877         float tcrange[4];
11878         float worldsize;
11879         int decalsequence;
11880 }
11881 r_decalsystem_splatqueue_t;
11882
11883 int r_decalsystem_numqueued = 0;
11884 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11885
11886 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)
11887 {
11888         r_decalsystem_splatqueue_t *queue;
11889
11890         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11891                 return;
11892
11893         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11894         VectorCopy(worldorigin, queue->worldorigin);
11895         VectorCopy(worldnormal, queue->worldnormal);
11896         Vector4Set(queue->color, r, g, b, a);
11897         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11898         queue->worldsize = worldsize;
11899         queue->decalsequence = cl.decalsequence++;
11900 }
11901
11902 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11903 {
11904         int i;
11905         r_decalsystem_splatqueue_t *queue;
11906
11907         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11908                 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);
11909         r_decalsystem_numqueued = 0;
11910 }
11911
11912 extern cvar_t cl_decals_max;
11913 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11914 {
11915         int i;
11916         decalsystem_t *decalsystem = &ent->decalsystem;
11917         int numdecals;
11918         int killsequence;
11919         tridecal_t *decal;
11920         float frametime;
11921         float lifetime;
11922
11923         if (!decalsystem->numdecals)
11924                 return;
11925
11926         if (r_showsurfaces.integer)
11927                 return;
11928
11929         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11930         {
11931                 R_DecalSystem_Reset(decalsystem);
11932                 return;
11933         }
11934
11935         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11936         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11937
11938         if (decalsystem->lastupdatetime)
11939                 frametime = (cl.time - decalsystem->lastupdatetime);
11940         else
11941                 frametime = 0;
11942         decalsystem->lastupdatetime = cl.time;
11943         decal = decalsystem->decals;
11944         numdecals = decalsystem->numdecals;
11945
11946         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11947         {
11948                 if (decal->color4ub[0][3])
11949                 {
11950                         decal->lived += frametime;
11951                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11952                         {
11953                                 memset(decal, 0, sizeof(*decal));
11954                                 if (decalsystem->freedecal > i)
11955                                         decalsystem->freedecal = i;
11956                         }
11957                 }
11958         }
11959         decal = decalsystem->decals;
11960         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
11961                 numdecals--;
11962
11963         // collapse the array by shuffling the tail decals into the gaps
11964         for (;;)
11965         {
11966                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
11967                         decalsystem->freedecal++;
11968                 if (decalsystem->freedecal == numdecals)
11969                         break;
11970                 decal[decalsystem->freedecal] = decal[--numdecals];
11971         }
11972
11973         decalsystem->numdecals = numdecals;
11974
11975         if (numdecals <= 0)
11976         {
11977                 // if there are no decals left, reset decalsystem
11978                 R_DecalSystem_Reset(decalsystem);
11979         }
11980 }
11981
11982 extern skinframe_t *decalskinframe;
11983 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11984 {
11985         int i;
11986         decalsystem_t *decalsystem = &ent->decalsystem;
11987         int numdecals;
11988         tridecal_t *decal;
11989         float faderate;
11990         float alpha;
11991         float *v3f;
11992         float *c4f;
11993         float *t2f;
11994         const int *e;
11995         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11996         int numtris = 0;
11997
11998         numdecals = decalsystem->numdecals;
11999         if (!numdecals)
12000                 return;
12001
12002         if (r_showsurfaces.integer)
12003                 return;
12004
12005         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12006         {
12007                 R_DecalSystem_Reset(decalsystem);
12008                 return;
12009         }
12010
12011         // if the model is static it doesn't matter what value we give for
12012         // wantnormals and wanttangents, so this logic uses only rules applicable
12013         // to a model, knowing that they are meaningless otherwise
12014         if (ent == r_refdef.scene.worldentity)
12015                 RSurf_ActiveWorldEntity();
12016         else
12017                 RSurf_ActiveModelEntity(ent, false, false, false);
12018
12019         decalsystem->lastupdatetime = cl.time;
12020         decal = decalsystem->decals;
12021
12022         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12023
12024         // update vertex positions for animated models
12025         v3f = decalsystem->vertex3f;
12026         c4f = decalsystem->color4f;
12027         t2f = decalsystem->texcoord2f;
12028         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12029         {
12030                 if (!decal->color4ub[0][3])
12031                         continue;
12032
12033                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12034                         continue;
12035
12036                 // update color values for fading decals
12037                 if (decal->lived >= cl_decals_time.value)
12038                 {
12039                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12040                         alpha *= (1.0f/255.0f);
12041                 }
12042                 else
12043                         alpha = 1.0f/255.0f;
12044
12045                 c4f[ 0] = decal->color4ub[0][0] * alpha;
12046                 c4f[ 1] = decal->color4ub[0][1] * alpha;
12047                 c4f[ 2] = decal->color4ub[0][2] * alpha;
12048                 c4f[ 3] = 1;
12049                 c4f[ 4] = decal->color4ub[1][0] * alpha;
12050                 c4f[ 5] = decal->color4ub[1][1] * alpha;
12051                 c4f[ 6] = decal->color4ub[1][2] * alpha;
12052                 c4f[ 7] = 1;
12053                 c4f[ 8] = decal->color4ub[2][0] * alpha;
12054                 c4f[ 9] = decal->color4ub[2][1] * alpha;
12055                 c4f[10] = decal->color4ub[2][2] * alpha;
12056                 c4f[11] = 1;
12057
12058                 t2f[0] = decal->texcoord2f[0][0];
12059                 t2f[1] = decal->texcoord2f[0][1];
12060                 t2f[2] = decal->texcoord2f[1][0];
12061                 t2f[3] = decal->texcoord2f[1][1];
12062                 t2f[4] = decal->texcoord2f[2][0];
12063                 t2f[5] = decal->texcoord2f[2][1];
12064
12065                 // update vertex positions for animated models
12066                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
12067                 {
12068                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12069                         VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
12070                         VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
12071                         VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
12072                 }
12073                 else
12074                 {
12075                         VectorCopy(decal->vertex3f[0], v3f);
12076                         VectorCopy(decal->vertex3f[1], v3f + 3);
12077                         VectorCopy(decal->vertex3f[2], v3f + 6);
12078                 }
12079
12080                 if (r_refdef.fogenabled)
12081                 {
12082                         alpha = RSurf_FogVertex(v3f);
12083                         VectorScale(c4f, alpha, c4f);
12084                         alpha = RSurf_FogVertex(v3f + 3);
12085                         VectorScale(c4f + 4, alpha, c4f + 4);
12086                         alpha = RSurf_FogVertex(v3f + 6);
12087                         VectorScale(c4f + 8, alpha, c4f + 8);
12088                 }
12089
12090                 v3f += 9;
12091                 c4f += 12;
12092                 t2f += 6;
12093                 numtris++;
12094         }
12095
12096         if (numtris > 0)
12097         {
12098                 r_refdef.stats.drawndecals += numtris;
12099
12100                 // now render the decals all at once
12101                 // (this assumes they all use one particle font texture!)
12102                 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);
12103                 R_Mesh_ResetTextureState();
12104                 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
12105                 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
12106                 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
12107                 GL_DepthMask(false);
12108                 GL_DepthRange(0, 1);
12109                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12110                 GL_DepthTest(true);
12111                 GL_CullFace(GL_NONE);
12112                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12113                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
12114                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
12115         }
12116 }
12117
12118 static void R_DrawModelDecals(void)
12119 {
12120         int i, numdecals;
12121
12122         // fade faster when there are too many decals
12123         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12124         for (i = 0;i < r_refdef.scene.numentities;i++)
12125                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12126
12127         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12128         for (i = 0;i < r_refdef.scene.numentities;i++)
12129                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12130                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12131
12132         R_DecalSystem_ApplySplatEntitiesQueue();
12133
12134         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12135         for (i = 0;i < r_refdef.scene.numentities;i++)
12136                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12137
12138         r_refdef.stats.totaldecals += numdecals;
12139
12140         if (r_showsurfaces.integer)
12141                 return;
12142
12143         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12144
12145         for (i = 0;i < r_refdef.scene.numentities;i++)
12146         {
12147                 if (!r_refdef.viewcache.entityvisible[i])
12148                         continue;
12149                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12150                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12151         }
12152 }
12153
12154 extern cvar_t mod_collision_bih;
12155 void R_DrawDebugModel(void)
12156 {
12157         entity_render_t *ent = rsurface.entity;
12158         int i, j, k, l, flagsmask;
12159         const msurface_t *surface;
12160         dp_model_t *model = ent->model;
12161         vec3_t v;
12162
12163         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12164
12165         R_Mesh_ColorPointer(NULL, 0, 0);
12166         R_Mesh_ResetTextureState();
12167         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12168         GL_DepthRange(0, 1);
12169         GL_DepthTest(!r_showdisabledepthtest.integer);
12170         GL_DepthMask(false);
12171         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12172
12173         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12174         {
12175                 int triangleindex;
12176                 int bihleafindex;
12177                 qboolean cullbox = ent == r_refdef.scene.worldentity;
12178                 const q3mbrush_t *brush;
12179                 const bih_t *bih = &model->collision_bih;
12180                 const bih_leaf_t *bihleaf;
12181                 float vertex3f[3][3];
12182                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12183                 cullbox = false;
12184                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12185                 {
12186                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12187                                 continue;
12188                         switch (bihleaf->type)
12189                         {
12190                         case BIH_BRUSH:
12191                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12192                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12193                                 {
12194                                         R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
12195                                         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);
12196                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
12197                                 }
12198                                 break;
12199                         case BIH_COLLISIONTRIANGLE:
12200                                 triangleindex = bihleaf->itemindex;
12201                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12202                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12203                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12204                                 R_Mesh_VertexPointer(vertex3f[0], 0, 0);
12205                                 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
12206                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, polygonelement3s, 0, 0);
12207                                 break;
12208                         case BIH_RENDERTRIANGLE:
12209                                 triangleindex = bihleaf->itemindex;
12210                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12211                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12212                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12213                                 R_Mesh_VertexPointer(vertex3f[0], 0, 0);
12214                                 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);
12215                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, polygonelement3s, 0, 0);
12216                                 break;
12217                         }
12218                 }
12219         }
12220
12221         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12222
12223         if (r_showtris.integer || r_shownormals.integer)
12224         {
12225                 if (r_showdisabledepthtest.integer)
12226                 {
12227                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12228                         GL_DepthMask(false);
12229                 }
12230                 else
12231                 {
12232                         GL_BlendFunc(GL_ONE, GL_ZERO);
12233                         GL_DepthMask(true);
12234                 }
12235                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12236                 {
12237                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12238                                 continue;
12239                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12240                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12241                         {
12242                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
12243                                 if (r_showtris.value > 0)
12244                                 {
12245                                         if (!rsurface.texture->currentlayers->depthmask)
12246                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12247                                         else if (ent == r_refdef.scene.worldentity)
12248                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12249                                         else
12250                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12251                                         R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
12252                                         R_Mesh_ColorPointer(NULL, 0, 0);
12253                                         R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
12254                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
12255                                         //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
12256                                         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);
12257                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
12258                                         CHECKGLERROR
12259                                 }
12260                                 if (r_shownormals.value < 0)
12261                                 {
12262                                         qglBegin(GL_LINES);
12263                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12264                                         {
12265                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
12266                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12267                                                 qglVertex3f(v[0], v[1], v[2]);
12268                                                 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
12269                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12270                                                 qglVertex3f(v[0], v[1], v[2]);
12271                                         }
12272                                         qglEnd();
12273                                         CHECKGLERROR
12274                                 }
12275                                 if (r_shownormals.value > 0)
12276                                 {
12277                                         qglBegin(GL_LINES);
12278                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12279                                         {
12280                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
12281                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12282                                                 qglVertex3f(v[0], v[1], v[2]);
12283                                                 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
12284                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12285                                                 qglVertex3f(v[0], v[1], v[2]);
12286                                         }
12287                                         qglEnd();
12288                                         CHECKGLERROR
12289                                         qglBegin(GL_LINES);
12290                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12291                                         {
12292                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
12293                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12294                                                 qglVertex3f(v[0], v[1], v[2]);
12295                                                 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
12296                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12297                                                 qglVertex3f(v[0], v[1], v[2]);
12298                                         }
12299                                         qglEnd();
12300                                         CHECKGLERROR
12301                                         qglBegin(GL_LINES);
12302                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12303                                         {
12304                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
12305                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12306                                                 qglVertex3f(v[0], v[1], v[2]);
12307                                                 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
12308                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12309                                                 qglVertex3f(v[0], v[1], v[2]);
12310                                         }
12311                                         qglEnd();
12312                                         CHECKGLERROR
12313                                 }
12314                         }
12315                 }
12316                 rsurface.texture = NULL;
12317         }
12318 }
12319
12320 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
12321 int r_maxsurfacelist = 0;
12322 const msurface_t **r_surfacelist = NULL;
12323 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12324 {
12325         int i, j, endj, flagsmask;
12326         dp_model_t *model = r_refdef.scene.worldmodel;
12327         msurface_t *surfaces;
12328         unsigned char *update;
12329         int numsurfacelist = 0;
12330         if (model == NULL)
12331                 return;
12332
12333         if (r_maxsurfacelist < model->num_surfaces)
12334         {
12335                 r_maxsurfacelist = model->num_surfaces;
12336                 if (r_surfacelist)
12337                         Mem_Free((msurface_t**)r_surfacelist);
12338                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12339         }
12340
12341         RSurf_ActiveWorldEntity();
12342
12343         surfaces = model->data_surfaces;
12344         update = model->brushq1.lightmapupdateflags;
12345
12346         // update light styles on this submodel
12347         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12348         {
12349                 model_brush_lightstyleinfo_t *style;
12350                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12351                 {
12352                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12353                         {
12354                                 int *list = style->surfacelist;
12355                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12356                                 for (j = 0;j < style->numsurfaces;j++)
12357                                         update[list[j]] = true;
12358                         }
12359                 }
12360         }
12361
12362         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12363
12364         if (debug)
12365         {
12366                 R_DrawDebugModel();
12367                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12368                 return;
12369         }
12370
12371         rsurface.uselightmaptexture = false;
12372         rsurface.texture = NULL;
12373         rsurface.rtlight = NULL;
12374         numsurfacelist = 0;
12375         // add visible surfaces to draw list
12376         for (i = 0;i < model->nummodelsurfaces;i++)
12377         {
12378                 j = model->sortedmodelsurfaces[i];
12379                 if (r_refdef.viewcache.world_surfacevisible[j])
12380                         r_surfacelist[numsurfacelist++] = surfaces + j;
12381         }
12382         // update lightmaps if needed
12383         if (model->brushq1.firstrender)
12384         {
12385                 model->brushq1.firstrender = false;
12386                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12387                         if (update[j])
12388                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12389         }
12390         else if (update)
12391         {
12392                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12393                         if (r_refdef.viewcache.world_surfacevisible[j])
12394                                 if (update[j])
12395                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12396         }
12397         // don't do anything if there were no surfaces
12398         if (!numsurfacelist)
12399         {
12400                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12401                 return;
12402         }
12403         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12404         GL_AlphaTest(false);
12405
12406         // add to stats if desired
12407         if (r_speeds.integer && !skysurfaces && !depthonly)
12408         {
12409                 r_refdef.stats.world_surfaces += numsurfacelist;
12410                 for (j = 0;j < numsurfacelist;j++)
12411                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
12412         }
12413
12414         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12415 }
12416
12417 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12418 {
12419         int i, j, endj, flagsmask;
12420         dp_model_t *model = ent->model;
12421         msurface_t *surfaces;
12422         unsigned char *update;
12423         int numsurfacelist = 0;
12424         if (model == NULL)
12425                 return;
12426
12427         if (r_maxsurfacelist < model->num_surfaces)
12428         {
12429                 r_maxsurfacelist = model->num_surfaces;
12430                 if (r_surfacelist)
12431                         Mem_Free((msurface_t **)r_surfacelist);
12432                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12433         }
12434
12435         // if the model is static it doesn't matter what value we give for
12436         // wantnormals and wanttangents, so this logic uses only rules applicable
12437         // to a model, knowing that they are meaningless otherwise
12438         if (ent == r_refdef.scene.worldentity)
12439                 RSurf_ActiveWorldEntity();
12440         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12441                 RSurf_ActiveModelEntity(ent, false, false, false);
12442         else if (prepass)
12443                 RSurf_ActiveModelEntity(ent, true, true, true);
12444         else if (depthonly)
12445         {
12446                 switch (vid.renderpath)
12447                 {
12448                 case RENDERPATH_GL20:
12449                 case RENDERPATH_CGGL:
12450                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12451                         break;
12452                 case RENDERPATH_GL13:
12453                 case RENDERPATH_GL11:
12454                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12455                         break;
12456                 }
12457         }
12458         else
12459         {
12460                 switch (vid.renderpath)
12461                 {
12462                 case RENDERPATH_GL20:
12463                 case RENDERPATH_CGGL:
12464                         RSurf_ActiveModelEntity(ent, true, true, false);
12465                         break;
12466                 case RENDERPATH_GL13:
12467                 case RENDERPATH_GL11:
12468                         RSurf_ActiveModelEntity(ent, true, false, false);
12469                         break;
12470                 }
12471         }
12472
12473         surfaces = model->data_surfaces;
12474         update = model->brushq1.lightmapupdateflags;
12475
12476         // update light styles
12477         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12478         {
12479                 model_brush_lightstyleinfo_t *style;
12480                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12481                 {
12482                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12483                         {
12484                                 int *list = style->surfacelist;
12485                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12486                                 for (j = 0;j < style->numsurfaces;j++)
12487                                         update[list[j]] = true;
12488                         }
12489                 }
12490         }
12491
12492         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12493
12494         if (debug)
12495         {
12496                 R_DrawDebugModel();
12497                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12498                 return;
12499         }
12500
12501         rsurface.uselightmaptexture = false;
12502         rsurface.texture = NULL;
12503         rsurface.rtlight = NULL;
12504         numsurfacelist = 0;
12505         // add visible surfaces to draw list
12506         for (i = 0;i < model->nummodelsurfaces;i++)
12507                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12508         // don't do anything if there were no surfaces
12509         if (!numsurfacelist)
12510         {
12511                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12512                 return;
12513         }
12514         // update lightmaps if needed
12515         if (update)
12516         {
12517                 int updated = 0;
12518                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12519                 {
12520                         if (update[j])
12521                         {
12522                                 updated++;
12523                                 R_BuildLightMap(ent, surfaces + j);
12524                         }
12525                 }
12526         }
12527         if (update)
12528                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12529                         if (update[j])
12530                                 R_BuildLightMap(ent, surfaces + j);
12531         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12532         GL_AlphaTest(false);
12533
12534         // add to stats if desired
12535         if (r_speeds.integer && !skysurfaces && !depthonly)
12536         {
12537                 r_refdef.stats.entities_surfaces += numsurfacelist;
12538                 for (j = 0;j < numsurfacelist;j++)
12539                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
12540         }
12541
12542         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12543 }
12544
12545 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12546 {
12547         static texture_t texture;
12548         static msurface_t surface;
12549         const msurface_t *surfacelist = &surface;
12550
12551         // fake enough texture and surface state to render this geometry
12552
12553         texture.update_lastrenderframe = -1; // regenerate this texture
12554         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12555         texture.currentskinframe = skinframe;
12556         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12557         texture.offsetmapping = OFFSETMAPPING_OFF;
12558         texture.offsetscale = 1;
12559         texture.specularscalemod = 1;
12560         texture.specularpowermod = 1;
12561
12562         surface.texture = &texture;
12563         surface.num_triangles = numtriangles;
12564         surface.num_firsttriangle = firsttriangle;
12565         surface.num_vertices = numvertices;
12566         surface.num_firstvertex = firstvertex;
12567
12568         // now render it
12569         rsurface.texture = R_GetCurrentTexture(surface.texture);
12570         rsurface.uselightmaptexture = false;
12571         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12572 }
12573
12574 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)
12575 {
12576         static msurface_t surface;
12577         const msurface_t *surfacelist = &surface;
12578
12579         // fake enough texture and surface state to render this geometry
12580
12581         surface.texture = texture;
12582         surface.num_triangles = numtriangles;
12583         surface.num_firsttriangle = firsttriangle;
12584         surface.num_vertices = numvertices;
12585         surface.num_firstvertex = firstvertex;
12586
12587         // now render it
12588         rsurface.texture = R_GetCurrentTexture(surface.texture);
12589         rsurface.uselightmaptexture = false;
12590         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12591 }