]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
WarpZones:
[divverent/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29
30 mempool_t *r_main_mempool;
31 rtexturepool_t *r_main_texturepool;
32
33 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
34
35 static qboolean r_loadnormalmap;
36 static qboolean r_loadgloss;
37 qboolean r_loadfog;
38 static qboolean r_loaddds;
39 static qboolean r_savedds;
40
41 //
42 // screen size info
43 //
44 r_refdef_t r_refdef;
45
46 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
47 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
48 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
49 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
50 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
51 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
52 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
53 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
54
55 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
56 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
57 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
58 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
59 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
60
61 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
62 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
63 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
64 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
65 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
66 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
67 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
68 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
69 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
70 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
71 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
72 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
73 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
74 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
75 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
76 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
77 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
78 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
79 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
80 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
81 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
82 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
83 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
84 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
85 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
86 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
87 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
88 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
89 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
90 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
91 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
92 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
93 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
94 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
95 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
96 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
97 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
98 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
99 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
100 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
101 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
102 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
103 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
104 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
105 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
106
107 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
108 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
109 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
110 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
111 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
112 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
113 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
114 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
115
116 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
117 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
118
119 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
120 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
121 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
122 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
123 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
124
125 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
126 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
127 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
128
129 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
130 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
131 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
132 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
133 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
134 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
135 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
136 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
137 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
138
139 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
140 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
141 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
142 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
143 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
144
145 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
146 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
147 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
148 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
149
150 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
151 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
152 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
153 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
154 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
155 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
156 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
157
158 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
159 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
160 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
161 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
162
163 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
164
165 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
166
167 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
168
169 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
170 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
171 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
172 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
173 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
174 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
175 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
176 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "16", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
177
178 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
179
180 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "1", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
181
182 extern cvar_t v_glslgamma;
183
184 extern qboolean v_flipped_state;
185
186 static struct r_bloomstate_s
187 {
188         qboolean enabled;
189         qboolean hdr;
190
191         int bloomwidth, bloomheight;
192
193         int screentexturewidth, screentextureheight;
194         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
195
196         int bloomtexturewidth, bloomtextureheight;
197         rtexture_t *texture_bloom;
198
199         // arrays for rendering the screen passes
200         float screentexcoord2f[8];
201         float bloomtexcoord2f[8];
202         float offsettexcoord2f[8];
203
204         r_viewport_t viewport;
205 }
206 r_bloomstate;
207
208 r_waterstate_t r_waterstate;
209
210 /// shadow volume bsp struct with automatically growing nodes buffer
211 svbsp_t r_svbsp;
212
213 rtexture_t *r_texture_blanknormalmap;
214 rtexture_t *r_texture_white;
215 rtexture_t *r_texture_grey128;
216 rtexture_t *r_texture_black;
217 rtexture_t *r_texture_notexture;
218 rtexture_t *r_texture_whitecube;
219 rtexture_t *r_texture_normalizationcube;
220 rtexture_t *r_texture_fogattenuation;
221 rtexture_t *r_texture_gammaramps;
222 unsigned int r_texture_gammaramps_serial;
223 //rtexture_t *r_texture_fogintensity;
224 rtexture_t *r_texture_reflectcube;
225
226 // TODO: hash lookups?
227 typedef struct cubemapinfo_s
228 {
229         char basename[64];
230         rtexture_t *texture;
231 }
232 cubemapinfo_t;
233
234 int r_texture_numcubemaps;
235 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
236
237 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
238 unsigned int r_numqueries;
239 unsigned int r_maxqueries;
240
241 typedef struct r_qwskincache_s
242 {
243         char name[MAX_QPATH];
244         skinframe_t *skinframe;
245 }
246 r_qwskincache_t;
247
248 static r_qwskincache_t *r_qwskincache;
249 static int r_qwskincache_size;
250
251 /// vertex coordinates for a quad that covers the screen exactly
252 const float r_screenvertex3f[12] =
253 {
254         0, 0, 0,
255         1, 0, 0,
256         1, 1, 0,
257         0, 1, 0
258 };
259
260 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
261 {
262         int i;
263         for (i = 0;i < verts;i++)
264         {
265                 out[0] = in[0] * r;
266                 out[1] = in[1] * g;
267                 out[2] = in[2] * b;
268                 out[3] = in[3];
269                 in += 4;
270                 out += 4;
271         }
272 }
273
274 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
275 {
276         int i;
277         for (i = 0;i < verts;i++)
278         {
279                 out[0] = r;
280                 out[1] = g;
281                 out[2] = b;
282                 out[3] = a;
283                 out += 4;
284         }
285 }
286
287 // FIXME: move this to client?
288 void FOG_clear(void)
289 {
290         if (gamemode == GAME_NEHAHRA)
291         {
292                 Cvar_Set("gl_fogenable", "0");
293                 Cvar_Set("gl_fogdensity", "0.2");
294                 Cvar_Set("gl_fogred", "0.3");
295                 Cvar_Set("gl_foggreen", "0.3");
296                 Cvar_Set("gl_fogblue", "0.3");
297         }
298         r_refdef.fog_density = 0;
299         r_refdef.fog_red = 0;
300         r_refdef.fog_green = 0;
301         r_refdef.fog_blue = 0;
302         r_refdef.fog_alpha = 1;
303         r_refdef.fog_start = 0;
304         r_refdef.fog_end = 16384;
305         r_refdef.fog_height = 1<<30;
306         r_refdef.fog_fadedepth = 128;
307 }
308
309 static void R_BuildBlankTextures(void)
310 {
311         unsigned char data[4];
312         data[2] = 128; // normal X
313         data[1] = 128; // normal Y
314         data[0] = 255; // normal Z
315         data[3] = 128; // height
316         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
317         data[0] = 255;
318         data[1] = 255;
319         data[2] = 255;
320         data[3] = 255;
321         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
322         data[0] = 128;
323         data[1] = 128;
324         data[2] = 128;
325         data[3] = 255;
326         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
327         data[0] = 0;
328         data[1] = 0;
329         data[2] = 0;
330         data[3] = 255;
331         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
332 }
333
334 static void R_BuildNoTexture(void)
335 {
336         int x, y;
337         unsigned char pix[16][16][4];
338         // this makes a light grey/dark grey checkerboard texture
339         for (y = 0;y < 16;y++)
340         {
341                 for (x = 0;x < 16;x++)
342                 {
343                         if ((y < 8) ^ (x < 8))
344                         {
345                                 pix[y][x][0] = 128;
346                                 pix[y][x][1] = 128;
347                                 pix[y][x][2] = 128;
348                                 pix[y][x][3] = 255;
349                         }
350                         else
351                         {
352                                 pix[y][x][0] = 64;
353                                 pix[y][x][1] = 64;
354                                 pix[y][x][2] = 64;
355                                 pix[y][x][3] = 255;
356                         }
357                 }
358         }
359         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
360 }
361
362 static void R_BuildWhiteCube(void)
363 {
364         unsigned char data[6*1*1*4];
365         memset(data, 255, sizeof(data));
366         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
367 }
368
369 static void R_BuildNormalizationCube(void)
370 {
371         int x, y, side;
372         vec3_t v;
373         vec_t s, t, intensity;
374 #define NORMSIZE 64
375         unsigned char *data;
376         data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
377         for (side = 0;side < 6;side++)
378         {
379                 for (y = 0;y < NORMSIZE;y++)
380                 {
381                         for (x = 0;x < NORMSIZE;x++)
382                         {
383                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
384                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
385                                 switch(side)
386                                 {
387                                 default:
388                                 case 0:
389                                         v[0] = 1;
390                                         v[1] = -t;
391                                         v[2] = -s;
392                                         break;
393                                 case 1:
394                                         v[0] = -1;
395                                         v[1] = -t;
396                                         v[2] = s;
397                                         break;
398                                 case 2:
399                                         v[0] = s;
400                                         v[1] = 1;
401                                         v[2] = t;
402                                         break;
403                                 case 3:
404                                         v[0] = s;
405                                         v[1] = -1;
406                                         v[2] = -t;
407                                         break;
408                                 case 4:
409                                         v[0] = s;
410                                         v[1] = -t;
411                                         v[2] = 1;
412                                         break;
413                                 case 5:
414                                         v[0] = -s;
415                                         v[1] = -t;
416                                         v[2] = -1;
417                                         break;
418                                 }
419                                 intensity = 127.0f / sqrt(DotProduct(v, v));
420                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
421                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
422                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
423                                 data[((side*64+y)*64+x)*4+3] = 255;
424                         }
425                 }
426         }
427         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
428         Mem_Free(data);
429 }
430
431 static void R_BuildFogTexture(void)
432 {
433         int x, b;
434 #define FOGWIDTH 256
435         unsigned char data1[FOGWIDTH][4];
436         //unsigned char data2[FOGWIDTH][4];
437         double d, r, alpha;
438
439         r_refdef.fogmasktable_start = r_refdef.fog_start;
440         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
441         r_refdef.fogmasktable_range = r_refdef.fogrange;
442         r_refdef.fogmasktable_density = r_refdef.fog_density;
443
444         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
445         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
446         {
447                 d = (x * r - r_refdef.fogmasktable_start);
448                 if(developer_extra.integer)
449                         Con_DPrintf("%f ", d);
450                 d = max(0, d);
451                 if (r_fog_exp2.integer)
452                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
453                 else
454                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
455                 if(developer_extra.integer)
456                         Con_DPrintf(" : %f ", alpha);
457                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
458                 if(developer_extra.integer)
459                         Con_DPrintf(" = %f\n", alpha);
460                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
461         }
462
463         for (x = 0;x < FOGWIDTH;x++)
464         {
465                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
466                 data1[x][0] = b;
467                 data1[x][1] = b;
468                 data1[x][2] = b;
469                 data1[x][3] = 255;
470                 //data2[x][0] = 255 - b;
471                 //data2[x][1] = 255 - b;
472                 //data2[x][2] = 255 - b;
473                 //data2[x][3] = 255;
474         }
475         if (r_texture_fogattenuation)
476         {
477                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
478                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
479         }
480         else
481         {
482                 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);
483                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
484         }
485 }
486
487 //=======================================================================================================================================================
488
489 static const char *builtinshaderstring =
490 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
491 "// written by Forest 'LordHavoc' Hale\n"
492 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
493 "\n"
494 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
495 "# define USEFOG\n"
496 "#endif\n"
497 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
498 "#define USELIGHTMAP\n"
499 "#endif\n"
500 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
501 "#define USEEYEVECTOR\n"
502 "#endif\n"
503 "\n"
504 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
505 "# extension GL_ARB_texture_rectangle : enable\n"
506 "#endif\n"
507 "\n"
508 "#ifdef USESHADOWMAP2D\n"
509 "# ifdef GL_EXT_gpu_shader4\n"
510 "#   extension GL_EXT_gpu_shader4 : enable\n"
511 "# endif\n"
512 "# ifdef GL_ARB_texture_gather\n"
513 "#   extension GL_ARB_texture_gather : enable\n"
514 "# else\n"
515 "#   ifdef GL_AMD_texture_texture4\n"
516 "#     extension GL_AMD_texture_texture4 : enable\n"
517 "#   endif\n"
518 "# endif\n"
519 "#endif\n"
520 "\n"
521 "#ifdef USESHADOWMAPCUBE\n"
522 "# extension GL_EXT_gpu_shader4 : enable\n"
523 "#endif\n"
524 "\n"
525 "//#ifdef USESHADOWSAMPLER\n"
526 "//# extension GL_ARB_shadow : enable\n"
527 "//#endif\n"
528 "\n"
529 "//#ifdef __GLSL_CG_DATA_TYPES\n"
530 "//# define myhalf half\n"
531 "//# define myhalf2 half2\n"
532 "//# define myhalf3 half3\n"
533 "//# define myhalf4 half4\n"
534 "//#else\n"
535 "# define myhalf float\n"
536 "# define myhalf2 vec2\n"
537 "# define myhalf3 vec3\n"
538 "# define myhalf4 vec4\n"
539 "//#endif\n"
540 "\n"
541 "#ifdef VERTEX_SHADER\n"
542 "uniform mat4 ModelViewProjectionMatrix;\n"
543 "#endif\n"
544 "\n"
545 "#ifdef MODE_DEPTH_OR_SHADOW\n"
546 "#ifdef VERTEX_SHADER\n"
547 "void main(void)\n"
548 "{\n"
549 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
550 "}\n"
551 "#endif\n"
552 "#else // !MODE_DEPTH_ORSHADOW\n"
553 "\n"
554 "\n"
555 "\n"
556 "\n"
557 "#ifdef MODE_SHOWDEPTH\n"
558 "#ifdef VERTEX_SHADER\n"
559 "void main(void)\n"
560 "{\n"
561 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
562 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
563 "}\n"
564 "#endif\n"
565 "\n"
566 "#ifdef FRAGMENT_SHADER\n"
567 "void main(void)\n"
568 "{\n"
569 "       gl_FragColor = gl_Color;\n"
570 "}\n"
571 "#endif\n"
572 "#else // !MODE_SHOWDEPTH\n"
573 "\n"
574 "\n"
575 "\n"
576 "\n"
577 "#ifdef MODE_POSTPROCESS\n"
578 "varying vec2 TexCoord1;\n"
579 "varying vec2 TexCoord2;\n"
580 "\n"
581 "#ifdef VERTEX_SHADER\n"
582 "void main(void)\n"
583 "{\n"
584 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
585 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
586 "#ifdef USEBLOOM\n"
587 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
588 "#endif\n"
589 "}\n"
590 "#endif\n"
591 "\n"
592 "#ifdef FRAGMENT_SHADER\n"
593 "uniform sampler2D Texture_First;\n"
594 "#ifdef USEBLOOM\n"
595 "uniform sampler2D Texture_Second;\n"
596 "#endif\n"
597 "#ifdef USEGAMMARAMPS\n"
598 "uniform sampler2D Texture_GammaRamps;\n"
599 "#endif\n"
600 "#ifdef USESATURATION\n"
601 "uniform float Saturation;\n"
602 "#endif\n"
603 "#ifdef USEVIEWTINT\n"
604 "uniform vec4 ViewTintColor;\n"
605 "#endif\n"
606 "//uncomment these if you want to use them:\n"
607 "uniform vec4 UserVec1;\n"
608 "// uniform vec4 UserVec2;\n"
609 "// uniform vec4 UserVec3;\n"
610 "// uniform vec4 UserVec4;\n"
611 "// uniform float ClientTime;\n"
612 "uniform vec2 PixelSize;\n"
613 "void main(void)\n"
614 "{\n"
615 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
616 "#ifdef USEBLOOM\n"
617 "       gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
618 "#endif\n"
619 "#ifdef USEVIEWTINT\n"
620 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
621 "#endif\n"
622 "\n"
623 "#ifdef USEPOSTPROCESSING\n"
624 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
625 "// 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"
626 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
627 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
628 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
629 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
630 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
631 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
632 "#endif\n"
633 "\n"
634 "#ifdef USESATURATION\n"
635 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
636 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
637 "       //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
638 "       gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
639 "#endif\n"
640 "\n"
641 "#ifdef USEGAMMARAMPS\n"
642 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
643 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
644 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
645 "#endif\n"
646 "}\n"
647 "#endif\n"
648 "#else // !MODE_POSTPROCESS\n"
649 "\n"
650 "\n"
651 "\n"
652 "\n"
653 "#ifdef MODE_GENERIC\n"
654 "#ifdef USEDIFFUSE\n"
655 "varying vec2 TexCoord1;\n"
656 "#endif\n"
657 "#ifdef USESPECULAR\n"
658 "varying vec2 TexCoord2;\n"
659 "#endif\n"
660 "#ifdef VERTEX_SHADER\n"
661 "void main(void)\n"
662 "{\n"
663 "       gl_FrontColor = gl_Color;\n"
664 "#ifdef USEDIFFUSE\n"
665 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
666 "#endif\n"
667 "#ifdef USESPECULAR\n"
668 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
669 "#endif\n"
670 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
671 "}\n"
672 "#endif\n"
673 "\n"
674 "#ifdef FRAGMENT_SHADER\n"
675 "#ifdef USEDIFFUSE\n"
676 "uniform sampler2D Texture_First;\n"
677 "#endif\n"
678 "#ifdef USESPECULAR\n"
679 "uniform sampler2D Texture_Second;\n"
680 "#endif\n"
681 "\n"
682 "void main(void)\n"
683 "{\n"
684 "       gl_FragColor = gl_Color;\n"
685 "#ifdef USEDIFFUSE\n"
686 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
687 "#endif\n"
688 "\n"
689 "#ifdef USESPECULAR\n"
690 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
691 "# ifdef USECOLORMAPPING\n"
692 "       gl_FragColor *= tex2;\n"
693 "# endif\n"
694 "# ifdef USEGLOW\n"
695 "       gl_FragColor += tex2;\n"
696 "# endif\n"
697 "# ifdef USEVERTEXTEXTUREBLEND\n"
698 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
699 "# endif\n"
700 "#endif\n"
701 "}\n"
702 "#endif\n"
703 "#else // !MODE_GENERIC\n"
704 "\n"
705 "\n"
706 "\n"
707 "\n"
708 "#ifdef MODE_BLOOMBLUR\n"
709 "varying TexCoord;\n"
710 "#ifdef VERTEX_SHADER\n"
711 "void main(void)\n"
712 "{\n"
713 "       gl_FrontColor = gl_Color;\n"
714 "       TexCoord = gl_MultiTexCoord0.xy;\n"
715 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
716 "}\n"
717 "#endif\n"
718 "\n"
719 "#ifdef FRAGMENT_SHADER\n"
720 "uniform sampler2D Texture_First;\n"
721 "uniform vec4 BloomBlur_Parameters;\n"
722 "\n"
723 "void main(void)\n"
724 "{\n"
725 "       int i;\n"
726 "       vec2 tc = TexCoord;\n"
727 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
728 "       tc += BloomBlur_Parameters.xy;\n"
729 "       for (i = 1;i < SAMPLES;i++)\n"
730 "       {\n"
731 "               color += texture2D(Texture_First, tc).rgb;\n"
732 "               tc += BloomBlur_Parameters.xy;\n"
733 "       }\n"
734 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
735 "}\n"
736 "#endif\n"
737 "#else // !MODE_BLOOMBLUR\n"
738 "#ifdef MODE_REFRACTION\n"
739 "varying vec2 TexCoord;\n"
740 "varying vec4 ModelViewProjectionPosition;\n"
741 "uniform mat4 TexMatrix;\n"
742 "#ifdef VERTEX_SHADER\n"
743 "\n"
744 "void main(void)\n"
745 "{\n"
746 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
747 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
748 "       ModelViewProjectionPosition = gl_Position;\n"
749 "}\n"
750 "#endif\n"
751 "\n"
752 "#ifdef FRAGMENT_SHADER\n"
753 "uniform sampler2D Texture_Normal;\n"
754 "uniform sampler2D Texture_Refraction;\n"
755 "uniform sampler2D Texture_Reflection;\n"
756 "\n"
757 "uniform vec4 DistortScaleRefractReflect;\n"
758 "uniform vec4 ScreenScaleRefractReflect;\n"
759 "uniform vec4 ScreenCenterRefractReflect;\n"
760 "uniform vec4 RefractColor;\n"
761 "uniform vec4 ReflectColor;\n"
762 "uniform float ReflectFactor;\n"
763 "uniform float ReflectOffset;\n"
764 "\n"
765 "void main(void)\n"
766 "{\n"
767 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
768 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
769 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
770 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
771 "       // FIXME temporary hack to detect the case that the reflection\n"
772 "       // gets blackened at edges due to leaving the area that contains actual\n"
773 "       // content.\n"
774 "       // Remove this 'ack once we have a better way to stop this thing from\n"
775 "       // 'appening.\n"
776 "       float 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 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
779 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
780 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
781 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
782 "}\n"
783 "#endif\n"
784 "#else // !MODE_REFRACTION\n"
785 "\n"
786 "\n"
787 "\n"
788 "\n"
789 "#ifdef MODE_WATER\n"
790 "varying vec2 TexCoord;\n"
791 "varying vec3 EyeVector;\n"
792 "varying vec4 ModelViewProjectionPosition;\n"
793 "#ifdef VERTEX_SHADER\n"
794 "uniform vec3 EyePosition;\n"
795 "uniform mat4 TexMatrix;\n"
796 "\n"
797 "void main(void)\n"
798 "{\n"
799 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
800 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
801 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
802 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
803 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
804 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
805 "       ModelViewProjectionPosition = gl_Position;\n"
806 "}\n"
807 "#endif\n"
808 "\n"
809 "#ifdef FRAGMENT_SHADER\n"
810 "uniform sampler2D Texture_Normal;\n"
811 "uniform sampler2D Texture_Refraction;\n"
812 "uniform sampler2D Texture_Reflection;\n"
813 "\n"
814 "uniform vec4 DistortScaleRefractReflect;\n"
815 "uniform vec4 ScreenScaleRefractReflect;\n"
816 "uniform vec4 ScreenCenterRefractReflect;\n"
817 "uniform vec4 RefractColor;\n"
818 "uniform vec4 ReflectColor;\n"
819 "uniform float ReflectFactor;\n"
820 "uniform float ReflectOffset;\n"
821 "\n"
822 "void main(void)\n"
823 "{\n"
824 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
825 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
826 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
827 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
828 "       vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
829 "       // FIXME temporary hack to detect the case that the reflection\n"
830 "       // gets blackened at edges due to leaving the area that contains actual\n"
831 "       // content.\n"
832 "       // Remove this 'ack once we have a better way to stop this thing from\n"
833 "       // 'appening.\n"
834 "       float 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 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
837 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
838 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\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 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
842 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
843 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
844 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
845 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
846 "}\n"
847 "#endif\n"
848 "#else // !MODE_WATER\n"
849 "\n"
850 "\n"
851 "\n"
852 "\n"
853 "// common definitions between vertex shader and fragment shader:\n"
854 "\n"
855 "varying vec2 TexCoord;\n"
856 "#ifdef USEVERTEXTEXTUREBLEND\n"
857 "varying vec2 TexCoord2;\n"
858 "#endif\n"
859 "#ifdef USELIGHTMAP\n"
860 "varying vec2 TexCoordLightmap;\n"
861 "#endif\n"
862 "\n"
863 "#ifdef MODE_LIGHTSOURCE\n"
864 "varying vec3 CubeVector;\n"
865 "#endif\n"
866 "\n"
867 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
868 "varying vec3 LightVector;\n"
869 "#endif\n"
870 "\n"
871 "#ifdef USEEYEVECTOR\n"
872 "varying vec3 EyeVector;\n"
873 "#endif\n"
874 "#ifdef USEFOG\n"
875 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
876 "#endif\n"
877 "\n"
878 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
879 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
880 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
881 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
882 "#endif\n"
883 "\n"
884 "#ifdef USEREFLECTION\n"
885 "varying vec4 ModelViewProjectionPosition;\n"
886 "#endif\n"
887 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
888 "uniform vec3 LightPosition;\n"
889 "varying vec4 ModelViewPosition;\n"
890 "#endif\n"
891 "\n"
892 "#ifdef MODE_LIGHTSOURCE\n"
893 "uniform vec3 LightPosition;\n"
894 "#endif\n"
895 "uniform vec3 EyePosition;\n"
896 "#ifdef MODE_LIGHTDIRECTION\n"
897 "uniform vec3 LightDir;\n"
898 "#endif\n"
899 "uniform vec4 FogPlane;\n"
900 "\n"
901 "#ifdef USESHADOWMAPORTHO\n"
902 "varying vec3 ShadowMapTC;\n"
903 "#endif\n"
904 "\n"
905 "\n"
906 "\n"
907 "\n"
908 "\n"
909 "// 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"
910 "\n"
911 "// fragment shader specific:\n"
912 "#ifdef FRAGMENT_SHADER\n"
913 "\n"
914 "uniform sampler2D Texture_Normal;\n"
915 "uniform sampler2D Texture_Color;\n"
916 "uniform sampler2D Texture_Gloss;\n"
917 "#ifdef USEGLOW\n"
918 "uniform sampler2D Texture_Glow;\n"
919 "#endif\n"
920 "#ifdef USEVERTEXTEXTUREBLEND\n"
921 "uniform sampler2D Texture_SecondaryNormal;\n"
922 "uniform sampler2D Texture_SecondaryColor;\n"
923 "uniform sampler2D Texture_SecondaryGloss;\n"
924 "#ifdef USEGLOW\n"
925 "uniform sampler2D Texture_SecondaryGlow;\n"
926 "#endif\n"
927 "#endif\n"
928 "#ifdef USECOLORMAPPING\n"
929 "uniform sampler2D Texture_Pants;\n"
930 "uniform sampler2D Texture_Shirt;\n"
931 "#endif\n"
932 "#ifdef USEFOG\n"
933 "uniform sampler2D Texture_FogMask;\n"
934 "#endif\n"
935 "#ifdef USELIGHTMAP\n"
936 "uniform sampler2D Texture_Lightmap;\n"
937 "#endif\n"
938 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
939 "uniform sampler2D Texture_Deluxemap;\n"
940 "#endif\n"
941 "#ifdef USEREFLECTION\n"
942 "uniform sampler2D Texture_Reflection;\n"
943 "#endif\n"
944 "\n"
945 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
946 "uniform sampler2D Texture_ScreenDepth;\n"
947 "uniform sampler2D Texture_ScreenNormalMap;\n"
948 "#endif\n"
949 "#ifdef USEDEFERREDLIGHTMAP\n"
950 "uniform sampler2D Texture_ScreenDiffuse;\n"
951 "uniform sampler2D Texture_ScreenSpecular;\n"
952 "#endif\n"
953 "\n"
954 "uniform myhalf3 Color_Pants;\n"
955 "uniform myhalf3 Color_Shirt;\n"
956 "uniform myhalf3 FogColor;\n"
957 "\n"
958 "#ifdef USEFOG\n"
959 "uniform float FogRangeRecip;\n"
960 "uniform float FogPlaneViewDist;\n"
961 "uniform float FogHeightFade;\n"
962 "float FogVertex(void)\n"
963 "{\n"
964 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
965 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
966 "       float fogfrac;\n"
967 "#ifdef USEFOGOUTSIDE\n"
968 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
969 "#else\n"
970 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
971 "#endif\n"
972 "       return float(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
973 "}\n"
974 "#endif\n"
975 "\n"
976 "#ifdef USEOFFSETMAPPING\n"
977 "uniform float OffsetMapping_Scale;\n"
978 "vec2 OffsetMapping(vec2 TexCoord)\n"
979 "{\n"
980 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
981 "       // 14 sample relief mapping: linear search and then binary search\n"
982 "       // this basically steps forward a small amount repeatedly until it finds\n"
983 "       // itself inside solid, then jitters forward and back using decreasing\n"
984 "       // amounts to find the impact\n"
985 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
986 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
987 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
988 "       vec3 RT = vec3(TexCoord, 1);\n"
989 "       OffsetVector *= 0.1;\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);\n"
998 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
999 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1000 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1001 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1002 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1003 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1004 "       return RT.xy;\n"
1005 "#else\n"
1006 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1007 "       // this basically moves forward the full distance, and then backs up based\n"
1008 "       // on height of samples\n"
1009 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1010 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1011 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1012 "       TexCoord += OffsetVector;\n"
1013 "       OffsetVector *= 0.333;\n"
1014 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1015 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1016 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1017 "       return TexCoord;\n"
1018 "#endif\n"
1019 "}\n"
1020 "#endif // USEOFFSETMAPPING\n"
1021 "\n"
1022 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1023 "uniform sampler2D Texture_Attenuation;\n"
1024 "uniform samplerCube Texture_Cube;\n"
1025 "#endif\n"
1026 "\n"
1027 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1028 "\n"
1029 "#ifdef USESHADOWMAPRECT\n"
1030 "# ifdef USESHADOWSAMPLER\n"
1031 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1032 "# else\n"
1033 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1034 "# endif\n"
1035 "#endif\n"
1036 "\n"
1037 "#ifdef USESHADOWMAP2D\n"
1038 "# ifdef USESHADOWSAMPLER\n"
1039 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1040 "# else\n"
1041 "uniform sampler2D Texture_ShadowMap2D;\n"
1042 "# endif\n"
1043 "#endif\n"
1044 "\n"
1045 "#ifdef USESHADOWMAPVSDCT\n"
1046 "uniform samplerCube Texture_CubeProjection;\n"
1047 "#endif\n"
1048 "\n"
1049 "#ifdef USESHADOWMAPCUBE\n"
1050 "# ifdef USESHADOWSAMPLER\n"
1051 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1052 "# else\n"
1053 "uniform samplerCube Texture_ShadowMapCube;\n"
1054 "# endif\n"
1055 "#endif\n"
1056 "\n"
1057 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1058 "uniform vec2 ShadowMap_TextureScale;\n"
1059 "uniform vec4 ShadowMap_Parameters;\n"
1060 "#endif\n"
1061 "\n"
1062 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1063 "# ifdef USESHADOWMAPORTHO\n"
1064 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1065 "# else\n"
1066 "#  ifdef USESHADOWMAPVSDCT\n"
1067 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1068 "{\n"
1069 "       vec3 adir = abs(dir);\n"
1070 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1071 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1072 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1073 "}\n"
1074 "#  else\n"
1075 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1076 "{\n"
1077 "       vec3 adir = abs(dir);\n"
1078 "       float ma = adir.z;\n"
1079 "       vec4 proj = vec4(dir, 2.5);\n"
1080 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1081 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1082 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1083 "       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"
1084 "}\n"
1085 "#  endif\n"
1086 "# endif\n"
1087 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1088 "\n"
1089 "#ifdef USESHADOWMAPCUBE\n"
1090 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1091 "{\n"
1092 "       vec3 adir = abs(dir);\n"
1093 "       return vec4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
1094 "}\n"
1095 "#endif\n"
1096 "\n"
1097 "# ifdef USESHADOWMAPRECT\n"
1098 "float ShadowMapCompare(vec3 dir)\n"
1099 "{\n"
1100 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1101 "       float f;\n"
1102 "#  ifdef USESHADOWSAMPLER\n"
1103 "\n"
1104 "#    ifdef USESHADOWMAPPCF\n"
1105 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1106 "       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"
1107 "#    else\n"
1108 "       f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1109 "#    endif\n"
1110 "\n"
1111 "#  else\n"
1112 "\n"
1113 "#    ifdef USESHADOWMAPPCF\n"
1114 "#      if USESHADOWMAPPCF > 1\n"
1115 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1116 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1117 "       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"
1118 "       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"
1119 "       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"
1120 "       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"
1121 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1122 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1123 "#      else\n"
1124 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1125 "       vec2 offset = fract(shadowmaptc.xy);\n"
1126 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1127 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1128 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1129 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1130 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1131 "#      endif\n"
1132 "#    else\n"
1133 "       f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1134 "#    endif\n"
1135 "\n"
1136 "#  endif\n"
1137 "#  ifdef USESHADOWMAPORTHO\n"
1138 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1139 "#  else\n"
1140 "       return f;\n"
1141 "#  endif\n"
1142 "}\n"
1143 "# endif\n"
1144 "\n"
1145 "# ifdef USESHADOWMAP2D\n"
1146 "float ShadowMapCompare(vec3 dir)\n"
1147 "{\n"
1148 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1149 "       float f;\n"
1150 "\n"
1151 "#  ifdef USESHADOWSAMPLER\n"
1152 "#    ifdef USESHADOWMAPPCF\n"
1153 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1154 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1155 "       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"
1156 "#    else\n"
1157 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1158 "#    endif\n"
1159 "#  else\n"
1160 "#    ifdef USESHADOWMAPPCF\n"
1161 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1162 "#      ifdef GL_ARB_texture_gather\n"
1163 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1164 "#      else\n"
1165 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1166 "#      endif\n"
1167 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1168 "#      if USESHADOWMAPPCF > 1\n"
1169 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1170 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1171 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1172 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
1173 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
1174 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
1175 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
1176 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
1177 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
1178 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
1179 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
1180 "       locols.yz += group2.ab;\n"
1181 "       hicols.yz += group8.rg;\n"
1182 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1183 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1184 "                               mix(locols, hicols, offset.y);\n"
1185 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1186 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1187 "       f = dot(cols, vec4(1.0/25.0));\n"
1188 "#      else\n"
1189 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1190 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1191 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1192 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1193 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1194 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1195 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1196 "#      endif\n"
1197 "#     else\n"
1198 "#      ifdef GL_EXT_gpu_shader4\n"
1199 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1200 "#      else\n"
1201 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1202 "#      endif\n"
1203 "#      if USESHADOWMAPPCF > 1\n"
1204 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1205 "       center *= ShadowMap_TextureScale;\n"
1206 "       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"
1207 "       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"
1208 "       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"
1209 "       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"
1210 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1211 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1212 "#      else\n"
1213 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1214 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1215 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1216 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1217 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1218 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1219 "#      endif\n"
1220 "#     endif\n"
1221 "#    else\n"
1222 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1223 "#    endif\n"
1224 "#  endif\n"
1225 "#  ifdef USESHADOWMAPORTHO\n"
1226 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1227 "#  else\n"
1228 "       return f;\n"
1229 "#  endif\n"
1230 "}\n"
1231 "# endif\n"
1232 "\n"
1233 "# ifdef USESHADOWMAPCUBE\n"
1234 "float ShadowMapCompare(vec3 dir)\n"
1235 "{\n"
1236 "       // apply depth texture cubemap as light filter\n"
1237 "       vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1238 "       float f;\n"
1239 "#  ifdef USESHADOWSAMPLER\n"
1240 "       f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1241 "#  else\n"
1242 "       f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1243 "#  endif\n"
1244 "       return f;\n"
1245 "}\n"
1246 "# endif\n"
1247 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1248 "#endif // FRAGMENT_SHADER\n"
1249 "\n"
1250 "\n"
1251 "\n"
1252 "\n"
1253 "#ifdef MODE_DEFERREDGEOMETRY\n"
1254 "#ifdef VERTEX_SHADER\n"
1255 "uniform mat4 TexMatrix;\n"
1256 "#ifdef USEVERTEXTEXTUREBLEND\n"
1257 "uniform mat4 BackgroundTexMatrix;\n"
1258 "#endif\n"
1259 "uniform mat4 ModelViewMatrix;\n"
1260 "void main(void)\n"
1261 "{\n"
1262 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1263 "#ifdef USEVERTEXTEXTUREBLEND\n"
1264 "       gl_FrontColor = gl_Color;\n"
1265 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1266 "#endif\n"
1267 "\n"
1268 "       // transform unnormalized eye direction into tangent space\n"
1269 "#ifdef USEOFFSETMAPPING\n"
1270 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1271 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1272 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1273 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1274 "#endif\n"
1275 "\n"
1276 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1277 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1278 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1279 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1280 "}\n"
1281 "#endif // VERTEX_SHADER\n"
1282 "\n"
1283 "#ifdef FRAGMENT_SHADER\n"
1284 "void main(void)\n"
1285 "{\n"
1286 "#ifdef USEOFFSETMAPPING\n"
1287 "       // apply offsetmapping\n"
1288 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1289 "#define TexCoord TexCoordOffset\n"
1290 "#endif\n"
1291 "\n"
1292 "#ifdef USEALPHAKILL\n"
1293 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1294 "               discard;\n"
1295 "#endif\n"
1296 "\n"
1297 "#ifdef USEVERTEXTEXTUREBLEND\n"
1298 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1299 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1300 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1301 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1302 "#endif\n"
1303 "\n"
1304 "#ifdef USEVERTEXTEXTUREBLEND\n"
1305 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1306 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1307 "#else\n"
1308 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1309 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1310 "#endif\n"
1311 "\n"
1312 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1313 "}\n"
1314 "#endif // FRAGMENT_SHADER\n"
1315 "#else // !MODE_DEFERREDGEOMETRY\n"
1316 "\n"
1317 "\n"
1318 "\n"
1319 "\n"
1320 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1321 "#ifdef VERTEX_SHADER\n"
1322 "uniform mat4 ModelViewMatrix;\n"
1323 "void main(void)\n"
1324 "{\n"
1325 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1326 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1327 "}\n"
1328 "#endif // VERTEX_SHADER\n"
1329 "\n"
1330 "#ifdef FRAGMENT_SHADER\n"
1331 "uniform mat4 ViewToLight;\n"
1332 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1333 "uniform vec2 ScreenToDepth;\n"
1334 "uniform myhalf3 DeferredColor_Ambient;\n"
1335 "uniform myhalf3 DeferredColor_Diffuse;\n"
1336 "#ifdef USESPECULAR\n"
1337 "uniform myhalf3 DeferredColor_Specular;\n"
1338 "uniform myhalf SpecularPower;\n"
1339 "#endif\n"
1340 "uniform myhalf2 PixelToScreenTexCoord;\n"
1341 "void main(void)\n"
1342 "{\n"
1343 "       // calculate viewspace pixel position\n"
1344 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1345 "       vec3 position;\n"
1346 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1347 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1348 "       // decode viewspace pixel normal\n"
1349 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1350 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1351 "       // surfacenormal = pixel normal in viewspace\n"
1352 "       // LightVector = pixel to light in viewspace\n"
1353 "       // CubeVector = position in lightspace\n"
1354 "       // eyevector = pixel to view in viewspace\n"
1355 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1356 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1357 "#ifdef USEDIFFUSE\n"
1358 "       // calculate diffuse shading\n"
1359 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1360 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1361 "#endif\n"
1362 "#ifdef USESPECULAR\n"
1363 "       // calculate directional shading\n"
1364 "       vec3 eyevector = position * -1.0;\n"
1365 "#  ifdef USEEXACTSPECULARMATH\n"
1366 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1367 "#  else\n"
1368 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1369 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1370 "#  endif\n"
1371 "#endif\n"
1372 "\n"
1373 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1374 "       fade *= ShadowMapCompare(CubeVector);\n"
1375 "#endif\n"
1376 "\n"
1377 "#ifdef USEDIFFUSE\n"
1378 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1379 "#else\n"
1380 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1381 "#endif\n"
1382 "#ifdef USESPECULAR\n"
1383 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1384 "#else\n"
1385 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1386 "#endif\n"
1387 "\n"
1388 "# ifdef USECUBEFILTER\n"
1389 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1390 "       gl_FragData[0].rgb *= cubecolor;\n"
1391 "       gl_FragData[1].rgb *= cubecolor;\n"
1392 "# endif\n"
1393 "}\n"
1394 "#endif // FRAGMENT_SHADER\n"
1395 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1396 "\n"
1397 "\n"
1398 "\n"
1399 "\n"
1400 "#ifdef VERTEX_SHADER\n"
1401 "uniform mat4 TexMatrix;\n"
1402 "#ifdef USEVERTEXTEXTUREBLEND\n"
1403 "uniform mat4 BackgroundTexMatrix;\n"
1404 "#endif\n"
1405 "#ifdef MODE_LIGHTSOURCE\n"
1406 "uniform mat4 ModelToLight;\n"
1407 "#endif\n"
1408 "#ifdef USESHADOWMAPORTHO\n"
1409 "uniform mat4 ShadowMapMatrix;\n"
1410 "#endif\n"
1411 "void main(void)\n"
1412 "{\n"
1413 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1414 "       gl_FrontColor = gl_Color;\n"
1415 "#endif\n"
1416 "       // copy the surface texcoord\n"
1417 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1418 "#ifdef USEVERTEXTEXTUREBLEND\n"
1419 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1420 "#endif\n"
1421 "#ifdef USELIGHTMAP\n"
1422 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1423 "#endif\n"
1424 "\n"
1425 "#ifdef MODE_LIGHTSOURCE\n"
1426 "       // transform vertex position into light attenuation/cubemap space\n"
1427 "       // (-1 to +1 across the light box)\n"
1428 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1429 "\n"
1430 "# ifdef USEDIFFUSE\n"
1431 "       // transform unnormalized light direction into tangent space\n"
1432 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1433 "       //  normalize it per pixel)\n"
1434 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1435 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1436 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1437 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1438 "# endif\n"
1439 "#endif\n"
1440 "\n"
1441 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1442 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1443 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1444 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1445 "#endif\n"
1446 "\n"
1447 "       // transform unnormalized eye direction into tangent space\n"
1448 "#ifdef USEEYEVECTOR\n"
1449 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1450 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1451 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1452 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1453 "#endif\n"
1454 "\n"
1455 "#ifdef USEFOG\n"
1456 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1457 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1458 "#endif\n"
1459 "\n"
1460 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1461 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1462 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1463 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1464 "#endif\n"
1465 "\n"
1466 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1467 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1468 "\n"
1469 "#ifdef USESHADOWMAPORTHO\n"
1470 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1471 "#endif\n"
1472 "\n"
1473 "#ifdef USEREFLECTION\n"
1474 "       ModelViewProjectionPosition = gl_Position;\n"
1475 "#endif\n"
1476 "}\n"
1477 "#endif // VERTEX_SHADER\n"
1478 "\n"
1479 "\n"
1480 "\n"
1481 "\n"
1482 "#ifdef FRAGMENT_SHADER\n"
1483 "#ifdef USEDEFERREDLIGHTMAP\n"
1484 "uniform myhalf2 PixelToScreenTexCoord;\n"
1485 "uniform myhalf3 DeferredMod_Diffuse;\n"
1486 "uniform myhalf3 DeferredMod_Specular;\n"
1487 "#endif\n"
1488 "uniform myhalf3 Color_Ambient;\n"
1489 "uniform myhalf3 Color_Diffuse;\n"
1490 "uniform myhalf3 Color_Specular;\n"
1491 "uniform myhalf SpecularPower;\n"
1492 "#ifdef USEGLOW\n"
1493 "uniform myhalf3 Color_Glow;\n"
1494 "#endif\n"
1495 "uniform myhalf Alpha;\n"
1496 "#ifdef USEREFLECTION\n"
1497 "uniform vec4 DistortScaleRefractReflect;\n"
1498 "uniform vec4 ScreenScaleRefractReflect;\n"
1499 "uniform vec4 ScreenCenterRefractReflect;\n"
1500 "uniform myhalf4 ReflectColor;\n"
1501 "#endif\n"
1502 "#ifdef USEREFLECTCUBE\n"
1503 "uniform mat4 ModelToReflectCube;\n"
1504 "uniform sampler2D Texture_ReflectMask;\n"
1505 "uniform samplerCube Texture_ReflectCube;\n"
1506 "#endif\n"
1507 "#ifdef MODE_LIGHTDIRECTION\n"
1508 "uniform myhalf3 LightColor;\n"
1509 "#endif\n"
1510 "#ifdef MODE_LIGHTSOURCE\n"
1511 "uniform myhalf3 LightColor;\n"
1512 "#endif\n"
1513 "void main(void)\n"
1514 "{\n"
1515 "#ifdef USEOFFSETMAPPING\n"
1516 "       // apply offsetmapping\n"
1517 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1518 "#define TexCoord TexCoordOffset\n"
1519 "#endif\n"
1520 "\n"
1521 "       // combine the diffuse textures (base, pants, shirt)\n"
1522 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1523 "#ifdef USEALPHAKILL\n"
1524 "       if (color.a < 0.5)\n"
1525 "               discard;\n"
1526 "#endif\n"
1527 "       color.a *= Alpha;\n"
1528 "#ifdef USECOLORMAPPING\n"
1529 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1530 "#endif\n"
1531 "#ifdef USEVERTEXTEXTUREBLEND\n"
1532 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1533 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1534 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1535 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1536 "       color.a = 1.0;\n"
1537 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1538 "#endif\n"
1539 "\n"
1540 "       // get the surface normal\n"
1541 "#ifdef USEVERTEXTEXTUREBLEND\n"
1542 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1543 "#else\n"
1544 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1545 "#endif\n"
1546 "\n"
1547 "       // get the material colors\n"
1548 "       myhalf3 diffusetex = color.rgb;\n"
1549 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1550 "# ifdef USEVERTEXTEXTUREBLEND\n"
1551 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1552 "# else\n"
1553 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1554 "# endif\n"
1555 "#endif\n"
1556 "\n"
1557 "#ifdef USEREFLECTCUBE\n"
1558 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1559 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1560 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1561 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1562 "#endif\n"
1563 "\n"
1564 "\n"
1565 "\n"
1566 "\n"
1567 "#ifdef MODE_LIGHTSOURCE\n"
1568 "       // light source\n"
1569 "#ifdef USEDIFFUSE\n"
1570 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1571 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1572 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1573 "#ifdef USESPECULAR\n"
1574 "#ifdef USEEXACTSPECULARMATH\n"
1575 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1576 "#else\n"
1577 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1578 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1579 "#endif\n"
1580 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1581 "#endif\n"
1582 "#else\n"
1583 "       color.rgb = diffusetex * Color_Ambient;\n"
1584 "#endif\n"
1585 "       color.rgb *= LightColor;\n"
1586 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1587 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1588 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1589 "#endif\n"
1590 "# ifdef USECUBEFILTER\n"
1591 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1592 "# endif\n"
1593 "#endif // MODE_LIGHTSOURCE\n"
1594 "\n"
1595 "\n"
1596 "\n"
1597 "\n"
1598 "#ifdef MODE_LIGHTDIRECTION\n"
1599 "#define SHADING\n"
1600 "#ifdef USEDIFFUSE\n"
1601 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1602 "#endif\n"
1603 "#define lightcolor LightColor\n"
1604 "#endif // MODE_LIGHTDIRECTION\n"
1605 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1606 "#define SHADING\n"
1607 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1608 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1609 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1610 "       // convert modelspace light vector to tangentspace\n"
1611 "       myhalf3 lightnormal;\n"
1612 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1613 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1614 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1615 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1616 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1617 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1618 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1619 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1620 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1621 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1622 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1623 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1624 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1625 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1626 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1627 "#define SHADING\n"
1628 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1629 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1630 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1631 "#endif\n"
1632 "\n"
1633 "\n"
1634 "\n"
1635 "\n"
1636 "#ifdef MODE_LIGHTMAP\n"
1637 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1638 "#endif // MODE_LIGHTMAP\n"
1639 "#ifdef MODE_VERTEXCOLOR\n"
1640 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1641 "#endif // MODE_VERTEXCOLOR\n"
1642 "#ifdef MODE_FLATCOLOR\n"
1643 "       color.rgb = diffusetex * Color_Ambient;\n"
1644 "#endif // MODE_FLATCOLOR\n"
1645 "\n"
1646 "\n"
1647 "\n"
1648 "\n"
1649 "#ifdef SHADING\n"
1650 "# ifdef USEDIFFUSE\n"
1651 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1652 "#  ifdef USESPECULAR\n"
1653 "#   ifdef USEEXACTSPECULARMATH\n"
1654 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1655 "#   else\n"
1656 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1657 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1658 "#   endif\n"
1659 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1660 "#  else\n"
1661 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1662 "#  endif\n"
1663 "# else\n"
1664 "       color.rgb = diffusetex * Color_Ambient;\n"
1665 "# endif\n"
1666 "#endif\n"
1667 "\n"
1668 "#ifdef USESHADOWMAPORTHO\n"
1669 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1670 "#endif\n"
1671 "\n"
1672 "#ifdef USEDEFERREDLIGHTMAP\n"
1673 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1674 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1675 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1676 "#endif\n"
1677 "\n"
1678 "#ifdef USEGLOW\n"
1679 "#ifdef USEVERTEXTEXTUREBLEND\n"
1680 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1681 "#else\n"
1682 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1683 "#endif\n"
1684 "#endif\n"
1685 "\n"
1686 "#ifdef USEFOG\n"
1687 "#ifdef MODE_LIGHTSOURCE\n"
1688 "       color.rgb *= myhalf(FogVertex());\n"
1689 "#else\n"
1690 "       color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1691 "#endif\n"
1692 "#endif\n"
1693 "\n"
1694 "       // 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"
1695 "#ifdef USEREFLECTION\n"
1696 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1697 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1698 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1699 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1700 "       // FIXME temporary hack to detect the case that the reflection\n"
1701 "       // gets blackened at edges due to leaving the area that contains actual\n"
1702 "       // content.\n"
1703 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1704 "       // 'appening.\n"
1705 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1706 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1707 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1708 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1709 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1710 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1711 "#endif\n"
1712 "\n"
1713 "       gl_FragColor = vec4(color);\n"
1714 "}\n"
1715 "#endif // FRAGMENT_SHADER\n"
1716 "\n"
1717 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1718 "#endif // !MODE_DEFERREDGEOMETRY\n"
1719 "#endif // !MODE_WATER\n"
1720 "#endif // !MODE_REFRACTION\n"
1721 "#endif // !MODE_BLOOMBLUR\n"
1722 "#endif // !MODE_GENERIC\n"
1723 "#endif // !MODE_POSTPROCESS\n"
1724 "#endif // !MODE_SHOWDEPTH\n"
1725 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1726 ;
1727
1728 /*
1729 =========================================================================================================================================================
1730
1731
1732
1733 =========================================================================================================================================================
1734
1735
1736
1737 =========================================================================================================================================================
1738
1739
1740
1741 =========================================================================================================================================================
1742
1743
1744
1745 =========================================================================================================================================================
1746
1747
1748
1749 =========================================================================================================================================================
1750
1751
1752
1753 =========================================================================================================================================================
1754 */
1755
1756 const char *builtincgshaderstring =
1757 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1758 "// written by Forest 'LordHavoc' Hale\n"
1759 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1760 "\n"
1761 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
1762 "# define USEFOG\n"
1763 "#endif\n"
1764 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1765 "#define USELIGHTMAP\n"
1766 "#endif\n"
1767 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
1768 "#define USEEYEVECTOR\n"
1769 "#endif\n"
1770 "\n"
1771 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1772 "#ifdef VERTEX_SHADER\n"
1773 "void main\n"
1774 "(\n"
1775 "float4 gl_Vertex : POSITION,\n"
1776 "uniform float4x4 ModelViewProjectionMatrix,\n"
1777 "out float4 gl_Position : POSITION\n"
1778 ")\n"
1779 "{\n"
1780 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1781 "}\n"
1782 "#endif\n"
1783 "#else // !MODE_DEPTH_ORSHADOW\n"
1784 "\n"
1785 "\n"
1786 "\n"
1787 "\n"
1788 "#ifdef MODE_SHOWDEPTH\n"
1789 "#ifdef VERTEX_SHADER\n"
1790 "void main\n"
1791 "(\n"
1792 "float4 gl_Vertex : POSITION,\n"
1793 "uniform float4x4 ModelViewProjectionMatrix,\n"
1794 "out float4 gl_Position : POSITION,\n"
1795 "out float4 gl_FrontColor : COLOR0\n"
1796 ")\n"
1797 "{\n"
1798 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1799 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1800 "}\n"
1801 "#endif\n"
1802 "\n"
1803 "#ifdef FRAGMENT_SHADER\n"
1804 "void main\n"
1805 "(\n"
1806 "float4 gl_FrontColor : COLOR0,\n"
1807 "out float4 gl_FragColor : COLOR\n"
1808 ")\n"
1809 "{\n"
1810 "       gl_FragColor = gl_FrontColor;\n"
1811 "}\n"
1812 "#endif\n"
1813 "#else // !MODE_SHOWDEPTH\n"
1814 "\n"
1815 "\n"
1816 "\n"
1817 "\n"
1818 "#ifdef MODE_POSTPROCESS\n"
1819 "\n"
1820 "#ifdef VERTEX_SHADER\n"
1821 "void main\n"
1822 "(\n"
1823 "float4 gl_Vertex : POSITION,\n"
1824 "uniform float4x4 ModelViewProjectionMatrix,\n"
1825 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1826 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1827 "out float4 gl_Position : POSITION,\n"
1828 "out float2 TexCoord1 : TEXCOORD0,\n"
1829 "out float2 TexCoord2 : TEXCOORD1\n"
1830 ")\n"
1831 "{\n"
1832 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1833 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1834 "#ifdef USEBLOOM\n"
1835 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1836 "#endif\n"
1837 "}\n"
1838 "#endif\n"
1839 "\n"
1840 "#ifdef FRAGMENT_SHADER\n"
1841 "void main\n"
1842 "(\n"
1843 "float2 TexCoord1 : TEXCOORD0,\n"
1844 "float2 TexCoord2 : TEXCOORD1,\n"
1845 "uniform sampler2D Texture_First,\n"
1846 "#ifdef USEBLOOM\n"
1847 "uniform sampler2D Texture_Second,\n"
1848 "#endif\n"
1849 "#ifdef USEGAMMARAMPS\n"
1850 "uniform sampler2D Texture_GammaRamps,\n"
1851 "#endif\n"
1852 "#ifdef USESATURATION\n"
1853 "uniform float Saturation,\n"
1854 "#endif\n"
1855 "#ifdef USEVIEWTINT\n"
1856 "uniform float4 ViewTintColor,\n"
1857 "#endif\n"
1858 "uniform float4 UserVec1,\n"
1859 "uniform float4 UserVec2,\n"
1860 "uniform float4 UserVec3,\n"
1861 "uniform float4 UserVec4,\n"
1862 "uniform float ClientTime,\n"
1863 "uniform float2 PixelSize,\n"
1864 "out float4 gl_FragColor : COLOR\n"
1865 ")\n"
1866 "{\n"
1867 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1868 "#ifdef USEBLOOM\n"
1869 "       gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
1870 "#endif\n"
1871 "#ifdef USEVIEWTINT\n"
1872 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1873 "#endif\n"
1874 "\n"
1875 "#ifdef USEPOSTPROCESSING\n"
1876 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1877 "// 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"
1878 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1879 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1880 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1881 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
1882 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
1883 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
1884 "#endif\n"
1885 "\n"
1886 "#ifdef USESATURATION\n"
1887 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
1888 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
1889 "       //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
1890 "       gl_FragColor.rgb = lerp(float3(y), gl_FragColor.rgb, Saturation);\n"
1891 "#endif\n"
1892 "\n"
1893 "#ifdef USEGAMMARAMPS\n"
1894 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
1895 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
1896 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
1897 "#endif\n"
1898 "}\n"
1899 "#endif\n"
1900 "#else // !MODE_POSTPROCESS\n"
1901 "\n"
1902 "\n"
1903 "\n"
1904 "\n"
1905 "#ifdef MODE_GENERIC\n"
1906 "#ifdef VERTEX_SHADER\n"
1907 "void main\n"
1908 "(\n"
1909 "float4 gl_Vertex : POSITION,\n"
1910 "uniform float4x4 ModelViewProjectionMatrix,\n"
1911 "float4 gl_Color : COLOR0,\n"
1912 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1913 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1914 "out float4 gl_Position : POSITION,\n"
1915 "out float4 gl_FrontColor : COLOR,\n"
1916 "out float2 TexCoord1 : TEXCOORD0,\n"
1917 "out float2 TexCoord2 : TEXCOORD1\n"
1918 ")\n"
1919 "{\n"
1920 "       gl_FrontColor = gl_Color;\n"
1921 "#ifdef USEDIFFUSE\n"
1922 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1923 "#endif\n"
1924 "#ifdef USESPECULAR\n"
1925 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1926 "#endif\n"
1927 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1928 "}\n"
1929 "#endif\n"
1930 "\n"
1931 "#ifdef FRAGMENT_SHADER\n"
1932 "\n"
1933 "void main\n"
1934 "(\n"
1935 "float4 gl_FrontColor : COLOR,\n"
1936 "float2 TexCoord1 : TEXCOORD0,\n"
1937 "float2 TexCoord2 : TEXCOORD1,\n"
1938 "#ifdef USEDIFFUSE\n"
1939 "uniform sampler2D Texture_First,\n"
1940 "#endif\n"
1941 "#ifdef USESPECULAR\n"
1942 "uniform sampler2D Texture_Second,\n"
1943 "#endif\n"
1944 "out float4 gl_FragColor : COLOR\n"
1945 ")\n"
1946 "{\n"
1947 "       gl_FragColor = gl_FrontColor;\n"
1948 "#ifdef USEDIFFUSE\n"
1949 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
1950 "#endif\n"
1951 "\n"
1952 "#ifdef USESPECULAR\n"
1953 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
1954 "# ifdef USECOLORMAPPING\n"
1955 "       gl_FragColor *= tex2;\n"
1956 "# endif\n"
1957 "# ifdef USEGLOW\n"
1958 "       gl_FragColor += tex2;\n"
1959 "# endif\n"
1960 "# ifdef USEVERTEXTEXTUREBLEND\n"
1961 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
1962 "# endif\n"
1963 "#endif\n"
1964 "}\n"
1965 "#endif\n"
1966 "#else // !MODE_GENERIC\n"
1967 "\n"
1968 "\n"
1969 "\n"
1970 "\n"
1971 "#ifdef MODE_BLOOMBLUR\n"
1972 "#ifdef VERTEX_SHADER\n"
1973 "void main\n"
1974 "(\n"
1975 "float4 gl_Vertex : POSITION,\n"
1976 "uniform float4x4 ModelViewProjectionMatrix,\n"
1977 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1978 "out float4 gl_Position : POSITION,\n"
1979 "out float2 TexCoord : TEXCOORD0\n"
1980 ")\n"
1981 "{\n"
1982 "       TexCoord = gl_MultiTexCoord0.xy;\n"
1983 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1984 "}\n"
1985 "#endif\n"
1986 "\n"
1987 "#ifdef FRAGMENT_SHADER\n"
1988 "\n"
1989 "void main\n"
1990 "(\n"
1991 "float2 TexCoord : TEXCOORD0,\n"
1992 "uniform sampler2D Texture_First,\n"
1993 "uniform float4 BloomBlur_Parameters,\n"
1994 "out float4 gl_FragColor : COLOR\n"
1995 ")\n"
1996 "{\n"
1997 "       int i;\n"
1998 "       float2 tc = TexCoord;\n"
1999 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2000 "       tc += BloomBlur_Parameters.xy;\n"
2001 "       for (i = 1;i < SAMPLES;i++)\n"
2002 "       {\n"
2003 "               color += tex2D(Texture_First, tc).rgb;\n"
2004 "               tc += BloomBlur_Parameters.xy;\n"
2005 "       }\n"
2006 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2007 "}\n"
2008 "#endif\n"
2009 "#else // !MODE_BLOOMBLUR\n"
2010 "#ifdef MODE_REFRACTION\n"
2011 "#ifdef VERTEX_SHADER\n"
2012 "void main\n"
2013 "(\n"
2014 "float4 gl_Vertex : POSITION,\n"
2015 "uniform float4x4 ModelViewProjectionMatrix,\n"
2016 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2017 "uniform float4x4 TexMatrix,\n"
2018 "uniform float3 EyePosition,\n"
2019 "out float4 gl_Position : POSITION,\n"
2020 "out float2 TexCoord : TEXCOORD0,\n"
2021 "out float3 EyeVector : TEXCOORD1,\n"
2022 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2023 ")\n"
2024 "{\n"
2025 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2026 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2027 "       ModelViewProjectionPosition = gl_Position;\n"
2028 "}\n"
2029 "#endif\n"
2030 "\n"
2031 "#ifdef FRAGMENT_SHADER\n"
2032 "void main\n"
2033 "(\n"
2034 "float2 TexCoord : TEXCOORD0,\n"
2035 "float3 EyeVector : TEXCOORD1,\n"
2036 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2037 "uniform sampler2D Texture_Normal,\n"
2038 "uniform sampler2D Texture_Refraction,\n"
2039 "uniform sampler2D Texture_Reflection,\n"
2040 "uniform float4 DistortScaleRefractReflect,\n"
2041 "uniform float4 ScreenScaleRefractReflect,\n"
2042 "uniform float4 ScreenCenterRefractReflect,\n"
2043 "uniform float4 RefractColor,\n"
2044 "out float4 gl_FragColor : COLOR\n"
2045 ")\n"
2046 "{\n"
2047 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2048 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2049 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2050 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
2051 "       // FIXME temporary hack to detect the case that the reflection\n"
2052 "       // gets blackened at edges due to leaving the area that contains actual\n"
2053 "       // content.\n"
2054 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2055 "       // 'appening.\n"
2056 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2057 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2058 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2059 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2060 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2061 "       gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2062 "}\n"
2063 "#endif\n"
2064 "#else // !MODE_REFRACTION\n"
2065 "\n"
2066 "\n"
2067 "\n"
2068 "\n"
2069 "#ifdef MODE_WATER\n"
2070 "#ifdef VERTEX_SHADER\n"
2071 "\n"
2072 "void main\n"
2073 "(\n"
2074 "float4 gl_Vertex : POSITION,\n"
2075 "uniform float4x4 ModelViewProjectionMatrix,\n"
2076 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2077 "uniform float4x4 TexMatrix,\n"
2078 "uniform float3 EyePosition,\n"
2079 "out float4 gl_Position : POSITION,\n"
2080 "out float2 TexCoord : TEXCOORD0,\n"
2081 "out float3 EyeVector : TEXCOORD1,\n"
2082 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2083 ")\n"
2084 "{\n"
2085 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2086 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2087 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2088 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2089 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2090 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2091 "       ModelViewProjectionPosition = gl_Position;\n"
2092 "}\n"
2093 "#endif\n"
2094 "\n"
2095 "#ifdef FRAGMENT_SHADER\n"
2096 "void main\n"
2097 "(\n"
2098 "float2 TexCoord : TEXCOORD0,\n"
2099 "float3 EyeVector : TEXCOORD1,\n"
2100 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2101 "uniform sampler2D Texture_Normal,\n"
2102 "uniform sampler2D Texture_Refraction,\n"
2103 "uniform sampler2D Texture_Reflection,\n"
2104 "uniform float4 DistortScaleRefractReflect,\n"
2105 "uniform float4 ScreenScaleRefractReflect,\n"
2106 "uniform float4 ScreenCenterRefractReflect,\n"
2107 "uniform float4 RefractColor,\n"
2108 "uniform float4 ReflectColor,\n"
2109 "uniform float ReflectFactor,\n"
2110 "uniform float ReflectOffset,\n"
2111 "out float4 gl_FragColor : COLOR\n"
2112 ")\n"
2113 "{\n"
2114 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2115 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2116 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2117 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xyxy * DistortScaleRefractReflect;\n"
2118 "       // FIXME temporary hack to detect the case that the reflection\n"
2119 "       // gets blackened at edges due to leaving the area that contains actual\n"
2120 "       // content.\n"
2121 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2122 "       // 'appening.\n"
2123 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2124 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2125 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2126 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2127 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2128 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2129 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2130 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2131 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2132 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2133 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2134 "       gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2135 "}\n"
2136 "#endif\n"
2137 "#else // !MODE_WATER\n"
2138 "\n"
2139 "\n"
2140 "\n"
2141 "\n"
2142 "// 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"
2143 "\n"
2144 "// fragment shader specific:\n"
2145 "#ifdef FRAGMENT_SHADER\n"
2146 "\n"
2147 "#ifdef USEFOG\n"
2148 "float FogVertex(float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask)\n"
2149 "{\n"
2150 "       float fogfrac;\n"
2151 "#ifdef USEFOGOUTSIDE\n"
2152 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2153 "#else\n"
2154 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2155 "#endif\n"
2156 "       return float(tex2D(Texture_FogMask, half2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
2157 "}\n"
2158 "#endif\n"
2159 "\n"
2160 "#ifdef USEOFFSETMAPPING\n"
2161 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler2D Texture_Normal)\n"
2162 "{\n"
2163 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2164 "       // 14 sample relief mapping: linear search and then binary search\n"
2165 "       // this basically steps forward a small amount repeatedly until it finds\n"
2166 "       // itself inside solid, then jitters forward and back using decreasing\n"
2167 "       // amounts to find the impact\n"
2168 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2169 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2170 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2171 "       float3 RT = float3(TexCoord, 1);\n"
2172 "       OffsetVector *= 0.1;\n"
2173 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2174 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2175 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2176 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2177 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2178 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2179 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2180 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2181 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2182 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2183 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2184 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2185 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2186 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2187 "       return RT.xy;\n"
2188 "#else\n"
2189 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2190 "       // this basically moves forward the full distance, and then backs up based\n"
2191 "       // on height of samples\n"
2192 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2193 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2194 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2195 "       TexCoord += OffsetVector;\n"
2196 "       OffsetVector *= 0.333;\n"
2197 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2198 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2199 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2200 "       return TexCoord;\n"
2201 "#endif\n"
2202 "}\n"
2203 "#endif // USEOFFSETMAPPING\n"
2204 "\n"
2205 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2206 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2207 "# ifdef USESHADOWMAPORTHO\n"
2208 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2209 "# else\n"
2210 "#  ifdef USESHADOWMAPVSDCT\n"
2211 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2212 "{\n"
2213 "       float3 adir = abs(dir);\n"
2214 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2215 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2216 "       return float3(lerp(dir.xy, proj.xy, dir.zz) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2217 "}\n"
2218 "#  else\n"
2219 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2220 "{\n"
2221 "       float3 adir = abs(dir);\n"
2222 "       float ma = adir.z;\n"
2223 "       float4 proj = float4(dir, 2.5);\n"
2224 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2225 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2226 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2227 "       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"
2228 "}\n"
2229 "#  endif\n"
2230 "# endif\n"
2231 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPORTHO)\n"
2232 "\n"
2233 "#ifdef USESHADOWMAPCUBE\n"
2234 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2235 "{\n"
2236 "    float3 adir = abs(dir);\n"
2237 "    return float4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
2238 "}\n"
2239 "#endif\n"
2240 "\n"
2241 "# ifdef USESHADOWMAPRECT\n"
2242 "#ifdef USESHADOWMAPVSDCT\n"
2243 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2244 "#else\n"
2245 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2246 "#endif\n"
2247 "{\n"
2248 "#ifdef USESHADOWMAPVSDCT\n"
2249 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2250 "#else\n"
2251 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2252 "#endif\n"
2253 "       float f;\n"
2254 "#  ifdef USESHADOWSAMPLER\n"
2255 "\n"
2256 "#    ifdef USESHADOWMAPPCF\n"
2257 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2258 "    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"
2259 "#    else\n"
2260 "    f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2261 "#    endif\n"
2262 "\n"
2263 "#  else\n"
2264 "\n"
2265 "#    ifdef USESHADOWMAPPCF\n"
2266 "#      if USESHADOWMAPPCF > 1\n"
2267 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2268 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2269 "    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"
2270 "    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"
2271 "    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"
2272 "    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"
2273 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2274 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2275 "#      else\n"
2276 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2277 "    float2 offset = frac(shadowmaptc.xy);\n"
2278 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2279 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2280 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2281 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2282 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2283 "#      endif\n"
2284 "#    else\n"
2285 "    f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2286 "#    endif\n"
2287 "\n"
2288 "#  endif\n"
2289 "#  ifdef USESHADOWMAPORTHO\n"
2290 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2291 "#  else\n"
2292 "       return f;\n"
2293 "#  endif\n"
2294 "}\n"
2295 "# endif\n"
2296 "\n"
2297 "# ifdef USESHADOWMAP2D\n"
2298 "#ifdef USESHADOWMAPVSDCT\n"
2299 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2300 "#else\n"
2301 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2302 "#endif\n"
2303 "{\n"
2304 "#ifdef USESHADOWMAPVSDCT\n"
2305 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2306 "#else\n"
2307 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2308 "#endif\n"
2309 "    float f;\n"
2310 "\n"
2311 "#  ifdef USESHADOWSAMPLER\n"
2312 "#    ifdef USESHADOWMAPPCF\n"
2313 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, float3(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
2314 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2315 "    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"
2316 "#    else\n"
2317 "    f = shadow2D(Texture_ShadowMap2D, float3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
2318 "#    endif\n"
2319 "#  else\n"
2320 "#    ifdef USESHADOWMAPPCF\n"
2321 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2322 "#      ifdef GL_ARB_texture_gather\n"
2323 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
2324 "#      else\n"
2325 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2326 "#      endif\n"
2327 "       float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2328 "#      if USESHADOWMAPPCF > 1\n"
2329 "       float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2330 "       float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2331 "       float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2332 "       float4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
2333 "       float4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
2334 "       float4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
2335 "       float4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
2336 "       float4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
2337 "       float4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
2338 "       float4 locols = float4(group1.ab, group3.ab);\n"
2339 "       float4 hicols = float4(group7.rg, group9.rg);\n"
2340 "       locols.yz += group2.ab;\n"
2341 "       hicols.yz += group8.rg;\n"
2342 "       float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2343 "                   float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2344 "                   lerp(locols, hicols, offset.y);\n"
2345 "       float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2346 "       cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2347 "       f = dot(cols, float4(1.0/25.0));\n"
2348 "#      else\n"
2349 "       float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2350 "       float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2351 "       float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2352 "       float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2353 "       float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2354 "                               lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2355 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2356 "#      endif\n"
2357 "#     else\n"
2358 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)  \n"
2359 "#      if USESHADOWMAPPCF > 1\n"
2360 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2361 "    center *= ShadowMap_TextureScale;\n"
2362 "    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"
2363 "    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"
2364 "    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"
2365 "    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"
2366 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2367 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2368 "#      else\n"
2369 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2370 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2371 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2372 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2373 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2374 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2375 "#      endif\n"
2376 "#     endif\n"
2377 "#    else\n"
2378 "    f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2379 "#    endif\n"
2380 "#  endif\n"
2381 "#  ifdef USESHADOWMAPORTHO\n"
2382 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2383 "#  else\n"
2384 "       return f;\n"
2385 "#  endif\n"
2386 "}\n"
2387 "# endif\n"
2388 "\n"
2389 "# ifdef USESHADOWMAPCUBE\n"
2390 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2391 "{\n"
2392 "    // apply depth texture cubemap as light filter\n"
2393 "    float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2394 "    float f;\n"
2395 "#  ifdef USESHADOWSAMPLER\n"
2396 "    f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2397 "#  else\n"
2398 "    f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2399 "#  endif\n"
2400 "    return f;\n"
2401 "}\n"
2402 "# endif\n"
2403 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2404 "#endif // FRAGMENT_SHADER\n"
2405 "\n"
2406 "\n"
2407 "\n"
2408 "\n"
2409 "#ifdef MODE_DEFERREDGEOMETRY\n"
2410 "#ifdef VERTEX_SHADER\n"
2411 "void main\n"
2412 "(\n"
2413 "float4 gl_Vertex : POSITION,\n"
2414 "uniform float4x4 ModelViewProjectionMatrix,\n"
2415 "#ifdef USEVERTEXTEXTUREBLEND\n"
2416 "float4 gl_Color : COLOR0,\n"
2417 "#endif\n"
2418 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2419 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2420 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2421 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2422 "uniform float4x4 TexMatrix,\n"
2423 "#ifdef USEVERTEXTEXTUREBLEND\n"
2424 "uniform float4x4 BackgroundTexMatrix,\n"
2425 "#endif\n"
2426 "uniform float4x4 ModelViewMatrix,\n"
2427 "#ifdef USEOFFSETMAPPING\n"
2428 "uniform float3 EyePosition,\n"
2429 "#endif\n"
2430 "out float4 gl_Position : POSITION,\n"
2431 "out float4 gl_FrontColor : COLOR,\n"
2432 "out float4 TexCoordBoth : TEXCOORD0,\n"
2433 "#ifdef USEOFFSETMAPPING\n"
2434 "out float3 EyeVector : TEXCOORD2,\n"
2435 "#endif\n"
2436 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2437 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2438 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2439 ")\n"
2440 "{\n"
2441 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2442 "#ifdef USEVERTEXTEXTUREBLEND\n"
2443 "       gl_FrontColor = gl_Color;\n"
2444 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2445 "#endif\n"
2446 "\n"
2447 "       // transform unnormalized eye direction into tangent space\n"
2448 "#ifdef USEOFFSETMAPPING\n"
2449 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2450 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2451 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2452 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2453 "#endif\n"
2454 "\n"
2455 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2456 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2457 "       VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2458 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2459 "}\n"
2460 "#endif // VERTEX_SHADER\n"
2461 "\n"
2462 "#ifdef FRAGMENT_SHADER\n"
2463 "void main\n"
2464 "(\n"
2465 "float4 TexCoordBoth : TEXCOORD0,\n"
2466 "float3 EyeVector : TEXCOORD2,\n"
2467 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2468 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2469 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2470 "uniform sampler2D Texture_Normal,\n"
2471 "#ifdef USEALPHAKILL\n"
2472 "uniform sampler2D Texture_Color,\n"
2473 "#endif\n"
2474 "uniform sampler2D Texture_Gloss,\n"
2475 "#ifdef USEVERTEXTEXTUREBLEND\n"
2476 "uniform sampler2D Texture_SecondaryNormal,\n"
2477 "uniform sampler2D Texture_SecondaryGloss,\n"
2478 "#endif\n"
2479 "#ifdef USEOFFSETMAPPING\n"
2480 "uniform float OffsetMapping_Scale,\n"
2481 "#endif\n"
2482 "uniform half SpecularPower,\n"
2483 "out float4 gl_FragColor : COLOR\n"
2484 ")\n"
2485 "{\n"
2486 "       float2 TexCoord = TexCoordBoth.xy;\n"
2487 "#ifdef USEOFFSETMAPPING\n"
2488 "       // apply offsetmapping\n"
2489 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2490 "#define TexCoord TexCoordOffset\n"
2491 "#endif\n"
2492 "\n"
2493 "#ifdef USEALPHAKILL\n"
2494 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2495 "               discard;\n"
2496 "#endif\n"
2497 "\n"
2498 "#ifdef USEVERTEXTEXTUREBLEND\n"
2499 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2500 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2501 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2502 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2503 "#endif\n"
2504 "\n"
2505 "#ifdef USEVERTEXTEXTUREBLEND\n"
2506 "       float3 surfacenormal = lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
2507 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2508 "#else\n"
2509 "       float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
2510 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2511 "#endif\n"
2512 "\n"
2513 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), 1);\n"
2514 "}\n"
2515 "#endif // FRAGMENT_SHADER\n"
2516 "#else // !MODE_DEFERREDGEOMETRY\n"
2517 "\n"
2518 "\n"
2519 "\n"
2520 "\n"
2521 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2522 "#ifdef VERTEX_SHADER\n"
2523 "void main\n"
2524 "(\n"
2525 "float4 gl_Vertex : POSITION,\n"
2526 "uniform float4x4 ModelViewProjectionMatrix,\n"
2527 "uniform float4x4 ModelViewMatrix,\n"
2528 "out float4 gl_Position : POSITION,\n"
2529 "out float4 ModelViewPosition : TEXCOORD0\n"
2530 ")\n"
2531 "{\n"
2532 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2533 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2534 "}\n"
2535 "#endif // VERTEX_SHADER\n"
2536 "\n"
2537 "#ifdef FRAGMENT_SHADER\n"
2538 "void main\n"
2539 "(\n"
2540 "float2 Pixel : WPOS,\n"
2541 "float4 ModelViewPosition : TEXCOORD0,\n"
2542 "uniform float4x4 ViewToLight,\n"
2543 "uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2544 "uniform float3 LightPosition,\n"
2545 "uniform half2 PixelToScreenTexCoord,\n"
2546 "uniform half3 DeferredColor_Ambient,\n"
2547 "uniform half3 DeferredColor_Diffuse,\n"
2548 "#ifdef USESPECULAR\n"
2549 "uniform half3 DeferredColor_Specular,\n"
2550 "uniform half SpecularPower,\n"
2551 "#endif\n"
2552 "uniform sampler2D Texture_Attenuation,\n"
2553 "uniform sampler2D Texture_ScreenDepth,\n"
2554 "uniform sampler2D Texture_ScreenNormalMap,\n"
2555 "\n"
2556 "#ifdef USESHADOWMAPRECT\n"
2557 "# ifdef USESHADOWSAMPLER\n"
2558 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2559 "# else\n"
2560 "uniform samplerRECT Texture_ShadowMapRect,\n"
2561 "# endif\n"
2562 "#endif\n"
2563 "\n"
2564 "#ifdef USESHADOWMAP2D\n"
2565 "# ifdef USESHADOWSAMPLER\n"
2566 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2567 "# else\n"
2568 "uniform sampler2D Texture_ShadowMap2D,\n"
2569 "# endif\n"
2570 "#endif\n"
2571 "\n"
2572 "#ifdef USESHADOWMAPVSDCT\n"
2573 "uniform samplerCUBE Texture_CubeProjection,\n"
2574 "#endif\n"
2575 "\n"
2576 "#ifdef USESHADOWMAPCUBE\n"
2577 "# ifdef USESHADOWSAMPLER\n"
2578 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2579 "# else\n"
2580 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2581 "# endif\n"
2582 "#endif\n"
2583 "\n"
2584 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2585 "uniform float2 ShadowMap_TextureScale,\n"
2586 "uniform float4 ShadowMap_Parameters,\n"
2587 "#endif\n"
2588 "\n"
2589 "out float4 gl_FragData0 : COLOR0,\n"
2590 "out float4 gl_FragData1 : COLOR1\n"
2591 ")\n"
2592 "{\n"
2593 "       // calculate viewspace pixel position\n"
2594 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2595 "       ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2596 "       float3 position;\n"
2597 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2598 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2599 "       // decode viewspace pixel normal\n"
2600 "       half4 normalmap = tex2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
2601 "       half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
2602 "       // surfacenormal = pixel normal in viewspace\n"
2603 "       // LightVector = pixel to light in viewspace\n"
2604 "       // CubeVector = position in lightspace\n"
2605 "       // eyevector = pixel to view in viewspace\n"
2606 "       float3 CubeVector = float3(mul(ViewToLight, float4(position,1)));\n"
2607 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2608 "#ifdef USEDIFFUSE\n"
2609 "       // calculate diffuse shading\n"
2610 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2611 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2612 "#endif\n"
2613 "#ifdef USESPECULAR\n"
2614 "       // calculate directional shading\n"
2615 "       float3 eyevector = position * -1.0;\n"
2616 "#  ifdef USEEXACTSPECULARMATH\n"
2617 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
2618 "#  else\n"
2619 "       half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
2620 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
2621 "#  endif\n"
2622 "#endif\n"
2623 "\n"
2624 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2625 "       fade *= ShadowMapCompare(CubeVector,\n"
2626 "# if defined(USESHADOWMAP2D)\n"
2627 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2628 "# endif\n"
2629 "# if defined(USESHADOWMAPRECT)\n"
2630 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2631 "# endif\n"
2632 "# if defined(USESHADOWMAPCUBE)\n"
2633 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2634 "# endif\n"
2635 "\n"
2636 "#ifdef USESHADOWMAPVSDCT\n"
2637 ", Texture_CubeProjection\n"
2638 "#endif\n"
2639 "       );\n"
2640 "#endif\n"
2641 "\n"
2642 "#ifdef USEDIFFUSE\n"
2643 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2644 "#else\n"
2645 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2646 "#endif\n"
2647 "#ifdef USESPECULAR\n"
2648 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2649 "#else\n"
2650 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2651 "#endif\n"
2652 "\n"
2653 "# ifdef USECUBEFILTER\n"
2654 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2655 "       gl_FragData0.rgb *= cubecolor;\n"
2656 "       gl_FragData1.rgb *= cubecolor;\n"
2657 "# endif\n"
2658 "}\n"
2659 "#endif // FRAGMENT_SHADER\n"
2660 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2661 "\n"
2662 "\n"
2663 "\n"
2664 "\n"
2665 "#ifdef VERTEX_SHADER\n"
2666 "void main\n"
2667 "(\n"
2668 "float4 gl_Vertex : POSITION,\n"
2669 "uniform float4x4 ModelViewProjectionMatrix,\n"
2670 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2671 "float4 gl_Color : COLOR0,\n"
2672 "#endif\n"
2673 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2674 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2675 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2676 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2677 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2678 "\n"
2679 "uniform float3 EyePosition,\n"
2680 "uniform float4x4 TexMatrix,\n"
2681 "#ifdef USEVERTEXTEXTUREBLEND\n"
2682 "uniform float4x4 BackgroundTexMatrix,\n"
2683 "#endif\n"
2684 "#ifdef MODE_LIGHTSOURCE\n"
2685 "uniform float4x4 ModelToLight,\n"
2686 "#endif\n"
2687 "#ifdef MODE_LIGHTSOURCE\n"
2688 "uniform float3 LightPosition,\n"
2689 "#endif\n"
2690 "#ifdef MODE_LIGHTDIRECTION\n"
2691 "uniform float3 LightDir,\n"
2692 "#endif\n"
2693 "uniform float4 FogPlane,\n"
2694 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2695 "uniform float3 LightPosition,\n"
2696 "#endif\n"
2697 "#ifdef USESHADOWMAPORTHO\n"
2698 "uniform float4x4 ShadowMapMatrix,\n"
2699 "#endif\n"
2700 "\n"
2701 "out float4 gl_FrontColor : COLOR,\n"
2702 "out float4 TexCoordBoth : TEXCOORD0,\n"
2703 "#ifdef USELIGHTMAP\n"
2704 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2705 "#endif\n"
2706 "#ifdef USEEYEVECTOR\n"
2707 "out float3 EyeVector : TEXCOORD2,\n"
2708 "#endif\n"
2709 "#ifdef USEREFLECTION\n"
2710 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2711 "#endif\n"
2712 "#ifdef USEFOG\n"
2713 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2714 "#endif\n"
2715 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2716 "out float3 LightVector : TEXCOORD1,\n"
2717 "#endif\n"
2718 "#ifdef MODE_LIGHTSOURCE\n"
2719 "out float3 CubeVector : TEXCOORD3,\n"
2720 "#endif\n"
2721 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2722 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2723 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2724 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2725 "#endif\n"
2726 "#ifdef USESHADOWMAPORTHO\n"
2727 "out float3 ShadowMapTC : TEXCOORD8,\n"
2728 "#endif\n"
2729 "out float4 gl_Position : POSITION\n"
2730 ")\n"
2731 "{\n"
2732 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2733 "       gl_FrontColor = gl_Color;\n"
2734 "#endif\n"
2735 "       // copy the surface texcoord\n"
2736 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2737 "#ifdef USEVERTEXTEXTUREBLEND\n"
2738 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2739 "#endif\n"
2740 "#ifdef USELIGHTMAP\n"
2741 "       TexCoordLightmap = float2(gl_MultiTexCoord4);\n"
2742 "#endif\n"
2743 "\n"
2744 "#ifdef MODE_LIGHTSOURCE\n"
2745 "       // transform vertex position into light attenuation/cubemap space\n"
2746 "       // (-1 to +1 across the light box)\n"
2747 "       CubeVector = float3(mul(ModelToLight, gl_Vertex));\n"
2748 "\n"
2749 "# ifdef USEDIFFUSE\n"
2750 "       // transform unnormalized light direction into tangent space\n"
2751 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2752 "       //  normalize it per pixel)\n"
2753 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2754 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2755 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2756 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2757 "# endif\n"
2758 "#endif\n"
2759 "\n"
2760 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2761 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2762 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2763 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2764 "#endif\n"
2765 "\n"
2766 "       // transform unnormalized eye direction into tangent space\n"
2767 "#ifdef USEEYEVECTOR\n"
2768 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2769 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2770 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2771 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2772 "#endif\n"
2773 "\n"
2774 "#ifdef USEFOG\n"
2775 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2776 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2777 "#endif\n"
2778 "\n"
2779 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
2780 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2781 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2782 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2783 "#endif\n"
2784 "\n"
2785 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2786 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2787 "\n"
2788 "#ifdef USESHADOWMAPORTHO\n"
2789 "       ShadowMapTC = float3(mul(ShadowMapMatrix, gl_Position));\n"
2790 "#endif\n"
2791 "\n"
2792 "#ifdef USEREFLECTION\n"
2793 "       ModelViewProjectionPosition = gl_Position;\n"
2794 "#endif\n"
2795 "}\n"
2796 "#endif // VERTEX_SHADER\n"
2797 "\n"
2798 "\n"
2799 "\n"
2800 "\n"
2801 "#ifdef FRAGMENT_SHADER\n"
2802 "void main\n"
2803 "(\n"
2804 "#ifdef USEDEFERREDLIGHTMAP\n"
2805 "float2 Pixel : WPOS,\n"
2806 "#endif\n"
2807 "float4 gl_FrontColor : COLOR,\n"
2808 "float4 TexCoordBoth : TEXCOORD0,\n"
2809 "#ifdef USELIGHTMAP\n"
2810 "float2 TexCoordLightmap : TEXCOORD1,\n"
2811 "#endif\n"
2812 "#ifdef USEEYEVECTOR\n"
2813 "float3 EyeVector : TEXCOORD2,\n"
2814 "#endif\n"
2815 "#ifdef USEREFLECTION\n"
2816 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2817 "#endif\n"
2818 "#ifdef USEFOG\n"
2819 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2820 "#endif\n"
2821 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2822 "float3 LightVector : TEXCOORD1,\n"
2823 "#endif\n"
2824 "#ifdef MODE_LIGHTSOURCE\n"
2825 "float3 CubeVector : TEXCOORD3,\n"
2826 "#endif\n"
2827 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2828 "float4 ModelViewPosition : TEXCOORD0,\n"
2829 "#endif\n"
2830 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2831 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2832 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2833 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2834 "#endif\n"
2835 "#ifdef USESHADOWMAPORTHO\n"
2836 "float3 ShadowMapTC : TEXCOORD8,\n"
2837 "#endif\n"
2838 "\n"
2839 "uniform sampler2D Texture_Normal,\n"
2840 "uniform sampler2D Texture_Color,\n"
2841 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2842 "uniform sampler2D Texture_Gloss,\n"
2843 "#endif\n"
2844 "#ifdef USEGLOW\n"
2845 "uniform sampler2D Texture_Glow,\n"
2846 "#endif\n"
2847 "#ifdef USEVERTEXTEXTUREBLEND\n"
2848 "uniform sampler2D Texture_SecondaryNormal,\n"
2849 "uniform sampler2D Texture_SecondaryColor,\n"
2850 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2851 "uniform sampler2D Texture_SecondaryGloss,\n"
2852 "#endif\n"
2853 "#ifdef USEGLOW\n"
2854 "uniform sampler2D Texture_SecondaryGlow,\n"
2855 "#endif\n"
2856 "#endif\n"
2857 "#ifdef USECOLORMAPPING\n"
2858 "uniform sampler2D Texture_Pants,\n"
2859 "uniform sampler2D Texture_Shirt,\n"
2860 "#endif\n"
2861 "#ifdef USEFOG\n"
2862 "uniform sampler2D Texture_FogMask,\n"
2863 "#endif\n"
2864 "#ifdef USELIGHTMAP\n"
2865 "uniform sampler2D Texture_Lightmap,\n"
2866 "#endif\n"
2867 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2868 "uniform sampler2D Texture_Deluxemap,\n"
2869 "#endif\n"
2870 "#ifdef USEREFLECTION\n"
2871 "uniform sampler2D Texture_Reflection,\n"
2872 "#endif\n"
2873 "\n"
2874 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2875 "uniform sampler2D Texture_ScreenDepth,\n"
2876 "uniform sampler2D Texture_ScreenNormalMap,\n"
2877 "#endif\n"
2878 "#ifdef USEDEFERREDLIGHTMAP\n"
2879 "uniform sampler2D Texture_ScreenDiffuse,\n"
2880 "uniform sampler2D Texture_ScreenSpecular,\n"
2881 "#endif\n"
2882 "\n"
2883 "#ifdef USECOLORMAPPING\n"
2884 "uniform half3 Color_Pants,\n"
2885 "uniform half3 Color_Shirt,\n"
2886 "#endif\n"
2887 "#ifdef USEFOG\n"
2888 "uniform float3 FogColor,\n"
2889 "uniform float FogRangeRecip,\n"
2890 "uniform float FogPlaneViewDist,\n"
2891 "uniform float FogHeightFade,\n"
2892 "#endif\n"
2893 "\n"
2894 "#ifdef USEOFFSETMAPPING\n"
2895 "uniform float OffsetMapping_Scale,\n"
2896 "#endif\n"
2897 "\n"
2898 "#ifdef USEDEFERREDLIGHTMAP\n"
2899 "uniform half2 PixelToScreenTexCoord,\n"
2900 "uniform half3 DeferredMod_Diffuse,\n"
2901 "uniform half3 DeferredMod_Specular,\n"
2902 "#endif\n"
2903 "uniform half3 Color_Ambient,\n"
2904 "uniform half3 Color_Diffuse,\n"
2905 "uniform half3 Color_Specular,\n"
2906 "uniform half SpecularPower,\n"
2907 "#ifdef USEGLOW\n"
2908 "uniform half3 Color_Glow,\n"
2909 "#endif\n"
2910 "uniform half Alpha,\n"
2911 "#ifdef USEREFLECTION\n"
2912 "uniform float4 DistortScaleRefractReflect,\n"
2913 "uniform float4 ScreenScaleRefractReflect,\n"
2914 "uniform float4 ScreenCenterRefractReflect,\n"
2915 "uniform half4 ReflectColor,\n"
2916 "#endif\n"
2917 "#ifdef USEREFLECTCUBE\n"
2918 "uniform float4x4 ModelToReflectCube,\n"
2919 "uniform sampler2D Texture_ReflectMask,\n"
2920 "uniform samplerCUBE Texture_ReflectCube,\n"
2921 "#endif\n"
2922 "#ifdef MODE_LIGHTDIRECTION\n"
2923 "uniform half3 LightColor,\n"
2924 "#endif\n"
2925 "#ifdef MODE_LIGHTSOURCE\n"
2926 "uniform half3 LightColor,\n"
2927 "#endif\n"
2928 "\n"
2929 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2930 "uniform sampler2D Texture_Attenuation,\n"
2931 "uniform samplerCUBE Texture_Cube,\n"
2932 "#endif\n"
2933 "\n"
2934 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2935 "\n"
2936 "#ifdef USESHADOWMAPRECT\n"
2937 "# ifdef USESHADOWSAMPLER\n"
2938 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2939 "# else\n"
2940 "uniform samplerRECT Texture_ShadowMapRect,\n"
2941 "# endif\n"
2942 "#endif\n"
2943 "\n"
2944 "#ifdef USESHADOWMAP2D\n"
2945 "# ifdef USESHADOWSAMPLER\n"
2946 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2947 "# else\n"
2948 "uniform sampler2D Texture_ShadowMap2D,\n"
2949 "# endif\n"
2950 "#endif\n"
2951 "\n"
2952 "#ifdef USESHADOWMAPVSDCT\n"
2953 "uniform samplerCUBE Texture_CubeProjection,\n"
2954 "#endif\n"
2955 "\n"
2956 "#ifdef USESHADOWMAPCUBE\n"
2957 "# ifdef USESHADOWSAMPLER\n"
2958 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2959 "# else\n"
2960 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2961 "# endif\n"
2962 "#endif\n"
2963 "\n"
2964 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2965 "uniform float2 ShadowMap_TextureScale,\n"
2966 "uniform float4 ShadowMap_Parameters,\n"
2967 "#endif\n"
2968 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2969 "\n"
2970 "out float4 gl_FragColor : COLOR\n"
2971 ")\n"
2972 "{\n"
2973 "       float2 TexCoord = TexCoordBoth.xy;\n"
2974 "#ifdef USEVERTEXTEXTUREBLEND\n"
2975 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
2976 "#endif\n"
2977 "#ifdef USEOFFSETMAPPING\n"
2978 "       // apply offsetmapping\n"
2979 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2980 "#define TexCoord TexCoordOffset\n"
2981 "#endif\n"
2982 "\n"
2983 "       // combine the diffuse textures (base, pants, shirt)\n"
2984 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
2985 "#ifdef USEALPHAKILL\n"
2986 "       if (color.a < 0.5)\n"
2987 "               discard;\n"
2988 "#endif\n"
2989 "       color.a *= Alpha;\n"
2990 "#ifdef USECOLORMAPPING\n"
2991 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord)) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
2992 "#endif\n"
2993 "#ifdef USEVERTEXTEXTUREBLEND\n"
2994 "       float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
2995 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
2996 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
2997 "       color.rgb = half3(lerp(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
2998 "       color.a = 1.0;\n"
2999 "       //color = lerp(half4(1, 0, 0, 1), color, terrainblend);\n"
3000 "#endif\n"
3001 "\n"
3002 "       // get the surface normal\n"
3003 "#ifdef USEVERTEXTEXTUREBLEND\n"
3004 "       half3 surfacenormal = normalize(half3(lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3005 "#else\n"
3006 "       half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
3007 "#endif\n"
3008 "\n"
3009 "       // get the material colors\n"
3010 "       half3 diffusetex = color.rgb;\n"
3011 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3012 "# ifdef USEVERTEXTEXTUREBLEND\n"
3013 "       half4 glosstex = half4(lerp(float4(tex2D(Texture_SecondaryGloss, TexCoord2)), float4(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
3014 "# else\n"
3015 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3016 "# endif\n"
3017 "#endif\n"
3018 "\n"
3019 "#ifdef USEREFLECTCUBE\n"
3020 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3021 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3022 "       float3 ReflectCubeTexCoord = float3(mul(ModelToReflectCube, float4(ModelReflectVector, 0)));\n"
3023 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord)) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord));\n"
3024 "#endif\n"
3025 "\n"
3026 "\n"
3027 "\n"
3028 "\n"
3029 "#ifdef MODE_LIGHTSOURCE\n"
3030 "       // light source\n"
3031 "#ifdef USEDIFFUSE\n"
3032 "       half3 lightnormal = half3(normalize(LightVector));\n"
3033 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3034 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3035 "#ifdef USESPECULAR\n"
3036 "#ifdef USEEXACTSPECULARMATH\n"
3037 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
3038 "#else\n"
3039 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3040 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
3041 "#endif\n"
3042 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3043 "#endif\n"
3044 "#else\n"
3045 "       color.rgb = diffusetex * Color_Ambient;\n"
3046 "#endif\n"
3047 "       color.rgb *= LightColor;\n"
3048 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
3049 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
3050 "       color.rgb *= ShadowMapCompare(CubeVector,\n"
3051 "# if defined(USESHADOWMAP2D)\n"
3052 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3053 "# endif\n"
3054 "# if defined(USESHADOWMAPRECT)\n"
3055 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3056 "# endif\n"
3057 "# if defined(USESHADOWMAPCUBE)\n"
3058 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
3059 "# endif\n"
3060 "\n"
3061 "#ifdef USESHADOWMAPVSDCT\n"
3062 ", Texture_CubeProjection\n"
3063 "#endif\n"
3064 "       );\n"
3065 "\n"
3066 "#endif\n"
3067 "# ifdef USECUBEFILTER\n"
3068 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector));\n"
3069 "# endif\n"
3070 "#endif // MODE_LIGHTSOURCE\n"
3071 "\n"
3072 "\n"
3073 "\n"
3074 "\n"
3075 "#ifdef MODE_LIGHTDIRECTION\n"
3076 "#define SHADING\n"
3077 "#ifdef USEDIFFUSE\n"
3078 "       half3 lightnormal = half3(normalize(LightVector));\n"
3079 "#endif\n"
3080 "#define lightcolor LightColor\n"
3081 "#endif // MODE_LIGHTDIRECTION\n"
3082 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3083 "#define SHADING\n"
3084 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3085 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3086 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3087 "       // convert modelspace light vector to tangentspace\n"
3088 "       half3 lightnormal;\n"
3089 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3090 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3091 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3092 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3093 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3094 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3095 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3096 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3097 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3098 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3099 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3100 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3101 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3102 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3103 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3104 "#define SHADING\n"
3105 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3106 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3107 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3108 "#endif\n"
3109 "\n"
3110 "\n"
3111 "\n"
3112 "\n"
3113 "#ifdef MODE_LIGHTMAP\n"
3114 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
3115 "#endif // MODE_LIGHTMAP\n"
3116 "#ifdef MODE_VERTEXCOLOR\n"
3117 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3118 "#endif // MODE_VERTEXCOLOR\n"
3119 "#ifdef MODE_FLATCOLOR\n"
3120 "       color.rgb = diffusetex * Color_Ambient;\n"
3121 "#endif // MODE_FLATCOLOR\n"
3122 "\n"
3123 "\n"
3124 "\n"
3125 "\n"
3126 "#ifdef SHADING\n"
3127 "# ifdef USEDIFFUSE\n"
3128 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3129 "#  ifdef USESPECULAR\n"
3130 "#   ifdef USEEXACTSPECULARMATH\n"
3131 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
3132 "#   else\n"
3133 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3134 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
3135 "#   endif\n"
3136 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3137 "#  else\n"
3138 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3139 "#  endif\n"
3140 "# else\n"
3141 "       color.rgb = diffusetex * Color_Ambient;\n"
3142 "# endif\n"
3143 "#endif\n"
3144 "\n"
3145 "#ifdef USESHADOWMAPORTHO\n"
3146 "       color.rgb *= ShadowMapCompare(ShadowMapTC,\n"
3147 "# if defined(USESHADOWMAP2D)\n"
3148 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3149 "# endif\n"
3150 "# if defined(USESHADOWMAPRECT)\n"
3151 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3152 "# endif\n"
3153 "       );\n"
3154 "#endif\n"
3155 "\n"
3156 "#ifdef USEDEFERREDLIGHTMAP\n"
3157 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3158 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
3159 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
3160 "#endif\n"
3161 "\n"
3162 "#ifdef USEGLOW\n"
3163 "#ifdef USEVERTEXTEXTUREBLEND\n"
3164 "       color.rgb += lerp(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
3165 "#else\n"
3166 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
3167 "#endif\n"
3168 "#endif\n"
3169 "\n"
3170 "#ifdef USEFOG\n"
3171 "#ifdef MODE_LIGHTSOURCE\n"
3172 "       color.rgb *= half(FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3173 "#else\n"
3174 "       color.rgb = lerp(FogColor, float3(color.rgb), FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3175 "#endif\n"
3176 "#endif\n"
3177 "\n"
3178 "       // 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"
3179 "#ifdef USEREFLECTION\n"
3180 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3181 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3182 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3183 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
3184 "       // FIXME temporary hack to detect the case that the reflection\n"
3185 "       // gets blackened at edges due to leaving the area that contains actual\n"
3186 "       // content.\n"
3187 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3188 "       // 'appening.\n"
3189 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3190 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3191 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3192 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3193 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3194 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
3195 "#endif\n"
3196 "\n"
3197 "       gl_FragColor = float4(color);\n"
3198 "}\n"
3199 "#endif // FRAGMENT_SHADER\n"
3200 "\n"
3201 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3202 "#endif // !MODE_DEFERREDGEOMETRY\n"
3203 "#endif // !MODE_WATER\n"
3204 "#endif // !MODE_REFRACTION\n"
3205 "#endif // !MODE_BLOOMBLUR\n"
3206 "#endif // !MODE_GENERIC\n"
3207 "#endif // !MODE_POSTPROCESS\n"
3208 "#endif // !MODE_SHOWDEPTH\n"
3209 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3210 ;
3211
3212 char *glslshaderstring = NULL;
3213 char *cgshaderstring = NULL;
3214
3215 //=======================================================================================================================================================
3216
3217 typedef struct shaderpermutationinfo_s
3218 {
3219         const char *pretext;
3220         const char *name;
3221 }
3222 shaderpermutationinfo_t;
3223
3224 typedef struct shadermodeinfo_s
3225 {
3226         const char *vertexfilename;
3227         const char *geometryfilename;
3228         const char *fragmentfilename;
3229         const char *pretext;
3230         const char *name;
3231 }
3232 shadermodeinfo_t;
3233
3234 typedef enum shaderpermutation_e
3235 {
3236         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3237         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3238         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3239         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3240         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3241         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3242         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3243         SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
3244         SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
3245         SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
3246         SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
3247         SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
3248         SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
3249         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3250         SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3251         SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3252         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3253         SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
3254         SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
3255         SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
3256         SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
3257         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3258         SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
3259         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3260         SHADERPERMUTATION_SHADOWMAPORTHO = 1<<24, //< (lightsource) use orthographic shadowmap projection
3261         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<25, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3262         SHADERPERMUTATION_ALPHAKILL = 1<<26, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3263         SHADERPERMUTATION_REFLECTCUBE = 1<<27, ///< fake reflections using global cubemap (not HDRI light probe)
3264         SHADERPERMUTATION_LIMIT = 1<<28, ///< size of permutations array
3265         SHADERPERMUTATION_COUNT = 28 ///< size of shaderpermutationinfo array
3266 }
3267 shaderpermutation_t;
3268
3269 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3270 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3271 {
3272         {"#define USEDIFFUSE\n", " diffuse"},
3273         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3274         {"#define USEVIEWTINT\n", " viewtint"},
3275         {"#define USECOLORMAPPING\n", " colormapping"},
3276         {"#define USESATURATION\n", " saturation"},
3277         {"#define USEFOGINSIDE\n", " foginside"},
3278         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3279         {"#define USEGAMMARAMPS\n", " gammaramps"},
3280         {"#define USECUBEFILTER\n", " cubefilter"},
3281         {"#define USEGLOW\n", " glow"},
3282         {"#define USEBLOOM\n", " bloom"},
3283         {"#define USESPECULAR\n", " specular"},
3284         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3285         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3286         {"#define USEREFLECTION\n", " reflection"},
3287         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3288         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3289         {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3290         {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3291         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3292         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3293         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3294         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3295         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3296         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3297         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3298         {"#define USEALPHAKILL\n", " alphakill"},
3299         {"#define USEREFLECTCUBE\n", " reflectcube"},
3300 };
3301
3302 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3303 typedef enum shadermode_e
3304 {
3305         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3306         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3307         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3308         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3309         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3310         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3311         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3312         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3313         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3314         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3315         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3316         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3317         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3318         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3319         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3320         SHADERMODE_COUNT
3321 }
3322 shadermode_t;
3323
3324 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3325 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3326 {
3327         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3328         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3329         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3330         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3331         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3332         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3333         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3334         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3335         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3336         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3337         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3338         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3339         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3340         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3341         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3342 };
3343
3344 #ifdef SUPPORTCG
3345 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3346 {
3347         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3348         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3349         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3350         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3351         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3352         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3353         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3354         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3355         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3356         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3357         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3358         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3359         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3360         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3361         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3362 };
3363 #endif
3364
3365 struct r_glsl_permutation_s;
3366 typedef struct r_glsl_permutation_s
3367 {
3368         /// hash lookup data
3369         struct r_glsl_permutation_s *hashnext;
3370         unsigned int mode;
3371         unsigned int permutation;
3372
3373         /// indicates if we have tried compiling this permutation already
3374         qboolean compiled;
3375         /// 0 if compilation failed
3376         int program;
3377         /// locations of detected uniforms in program object, or -1 if not found
3378         int loc_Texture_First;
3379         int loc_Texture_Second;
3380         int loc_Texture_GammaRamps;
3381         int loc_Texture_Normal;
3382         int loc_Texture_Color;
3383         int loc_Texture_Gloss;
3384         int loc_Texture_Glow;
3385         int loc_Texture_SecondaryNormal;
3386         int loc_Texture_SecondaryColor;
3387         int loc_Texture_SecondaryGloss;
3388         int loc_Texture_SecondaryGlow;
3389         int loc_Texture_Pants;
3390         int loc_Texture_Shirt;
3391         int loc_Texture_FogMask;
3392         int loc_Texture_Lightmap;
3393         int loc_Texture_Deluxemap;
3394         int loc_Texture_Attenuation;
3395         int loc_Texture_Cube;
3396         int loc_Texture_Refraction;
3397         int loc_Texture_Reflection;
3398         int loc_Texture_ShadowMapRect;
3399         int loc_Texture_ShadowMapCube;
3400         int loc_Texture_ShadowMap2D;
3401         int loc_Texture_CubeProjection;
3402         int loc_Texture_ScreenDepth;
3403         int loc_Texture_ScreenNormalMap;
3404         int loc_Texture_ScreenDiffuse;
3405         int loc_Texture_ScreenSpecular;
3406         int loc_Texture_ReflectMask;
3407         int loc_Texture_ReflectCube;
3408         int loc_Alpha;
3409         int loc_BloomBlur_Parameters;
3410         int loc_ClientTime;
3411         int loc_Color_Ambient;
3412         int loc_Color_Diffuse;
3413         int loc_Color_Specular;
3414         int loc_Color_Glow;
3415         int loc_Color_Pants;
3416         int loc_Color_Shirt;
3417         int loc_DeferredColor_Ambient;
3418         int loc_DeferredColor_Diffuse;
3419         int loc_DeferredColor_Specular;
3420         int loc_DeferredMod_Diffuse;
3421         int loc_DeferredMod_Specular;
3422         int loc_DistortScaleRefractReflect;
3423         int loc_EyePosition;
3424         int loc_FogColor;
3425         int loc_FogHeightFade;
3426         int loc_FogPlane;
3427         int loc_FogPlaneViewDist;
3428         int loc_FogRangeRecip;
3429         int loc_LightColor;
3430         int loc_LightDir;
3431         int loc_LightPosition;
3432         int loc_OffsetMapping_Scale;
3433         int loc_PixelSize;
3434         int loc_ReflectColor;
3435         int loc_ReflectFactor;
3436         int loc_ReflectOffset;
3437         int loc_RefractColor;
3438         int loc_Saturation;
3439         int loc_ScreenCenterRefractReflect;
3440         int loc_ScreenScaleRefractReflect;
3441         int loc_ScreenToDepth;
3442         int loc_ShadowMap_Parameters;
3443         int loc_ShadowMap_TextureScale;
3444         int loc_SpecularPower;
3445         int loc_UserVec1;
3446         int loc_UserVec2;
3447         int loc_UserVec3;
3448         int loc_UserVec4;
3449         int loc_ViewTintColor;
3450         int loc_ViewToLight;
3451         int loc_ModelToLight;
3452         int loc_TexMatrix;
3453         int loc_BackgroundTexMatrix;
3454         int loc_ModelViewProjectionMatrix;
3455         int loc_ModelViewMatrix;
3456         int loc_PixelToScreenTexCoord;
3457         int loc_ModelToReflectCube;
3458         int loc_ShadowMapMatrix;        
3459 }
3460 r_glsl_permutation_t;
3461
3462 #define SHADERPERMUTATION_HASHSIZE 256
3463
3464 /// information about each possible shader permutation
3465 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3466 /// currently selected permutation
3467 r_glsl_permutation_t *r_glsl_permutation;
3468 /// storage for permutations linked in the hash table
3469 memexpandablearray_t r_glsl_permutationarray;
3470
3471 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3472 {
3473         //unsigned int hashdepth = 0;
3474         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3475         r_glsl_permutation_t *p;
3476         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3477         {
3478                 if (p->mode == mode && p->permutation == permutation)
3479                 {
3480                         //if (hashdepth > 10)
3481                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3482                         return p;
3483                 }
3484                 //hashdepth++;
3485         }
3486         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3487         p->mode = mode;
3488         p->permutation = permutation;
3489         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3490         r_glsl_permutationhash[mode][hashindex] = p;
3491         //if (hashdepth > 10)
3492         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3493         return p;
3494 }
3495
3496 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3497 {
3498         char *shaderstring;
3499         if (!filename || !filename[0])
3500                 return NULL;
3501         if (!strcmp(filename, "glsl/default.glsl"))
3502         {
3503                 if (!glslshaderstring)
3504                 {
3505                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3506                         if (glslshaderstring)
3507                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3508                         else
3509                                 glslshaderstring = (char *)builtinshaderstring;
3510                 }
3511                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3512                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3513                 return shaderstring;
3514         }
3515         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3516         if (shaderstring)
3517         {
3518                 if (printfromdisknotice)
3519                         Con_DPrintf("from disk %s... ", filename);
3520                 return shaderstring;
3521         }
3522         return shaderstring;
3523 }
3524
3525 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3526 {
3527         int i;
3528         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3529         int vertstrings_count = 0;
3530         int geomstrings_count = 0;
3531         int fragstrings_count = 0;
3532         char *vertexstring, *geometrystring, *fragmentstring;
3533         const char *vertstrings_list[32+3];
3534         const char *geomstrings_list[32+3];
3535         const char *fragstrings_list[32+3];
3536         char permutationname[256];
3537
3538         if (p->compiled)
3539                 return;
3540         p->compiled = true;
3541         p->program = 0;
3542
3543         permutationname[0] = 0;
3544         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3545         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3546         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3547
3548         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3549
3550         // the first pretext is which type of shader to compile as
3551         // (later these will all be bound together as a program object)
3552         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3553         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3554         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3555
3556         // the second pretext is the mode (for example a light source)
3557         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3558         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3559         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3560         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3561
3562         // now add all the permutation pretexts
3563         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3564         {
3565                 if (permutation & (1<<i))
3566                 {
3567                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3568                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3569                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3570                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3571                 }
3572                 else
3573                 {
3574                         // keep line numbers correct
3575                         vertstrings_list[vertstrings_count++] = "\n";
3576                         geomstrings_list[geomstrings_count++] = "\n";
3577                         fragstrings_list[fragstrings_count++] = "\n";
3578                 }
3579         }
3580
3581         // now append the shader text itself
3582         vertstrings_list[vertstrings_count++] = vertexstring;
3583         geomstrings_list[geomstrings_count++] = geometrystring;
3584         fragstrings_list[fragstrings_count++] = fragmentstring;
3585
3586         // if any sources were NULL, clear the respective list
3587         if (!vertexstring)
3588                 vertstrings_count = 0;
3589         if (!geometrystring)
3590                 geomstrings_count = 0;
3591         if (!fragmentstring)
3592                 fragstrings_count = 0;
3593
3594         // compile the shader program
3595         if (vertstrings_count + geomstrings_count + fragstrings_count)
3596                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3597         if (p->program)
3598         {
3599                 CHECKGLERROR
3600                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3601                 // look up all the uniform variable names we care about, so we don't
3602                 // have to look them up every time we set them
3603
3604                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3605                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3606                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3607                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3608                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3609                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3610                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3611                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3612                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3613                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3614                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3615                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3616                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3617                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3618                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3619                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3620                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3621                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3622                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3623                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3624                 p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3625                 p->loc_Texture_ShadowMapCube      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3626                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3627                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3628                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3629                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3630                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3631                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3632                 p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3633                 p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3634                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3635                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3636                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3637                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3638                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3639                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3640                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3641                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3642                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3643                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3644                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3645                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3646                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3647                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3648                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3649                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3650                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3651                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3652                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3653                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3654                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3655                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3656                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3657                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3658                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3659                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3660                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3661                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3662                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3663                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3664                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3665                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3666                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3667                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3668                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3669                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3670                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3671                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3672                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3673                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3674                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3675                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3676                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3677                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3678                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3679                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3680                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3681                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3682                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3683                 p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3684                 p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");            
3685                 // initialize the samplers to refer to the texture units we use
3686                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3687                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3688                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3689                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3690                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3691                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3692                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3693                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3694                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3695                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3696                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3697                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3698                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3699                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3700                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3701                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3702                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3703                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3704                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3705                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3706                 if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT);
3707                 if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
3708                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D);
3709                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3710                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3711                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3712                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3713                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3714                 if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
3715                 if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
3716                 CHECKGLERROR
3717                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3718         }
3719         else
3720                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3721
3722         // free the strings
3723         if (vertexstring)
3724                 Mem_Free(vertexstring);
3725         if (geometrystring)
3726                 Mem_Free(geometrystring);
3727         if (fragmentstring)
3728                 Mem_Free(fragmentstring);
3729 }
3730
3731 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3732 {
3733         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3734         if (r_glsl_permutation != perm)
3735         {
3736                 r_glsl_permutation = perm;
3737                 if (!r_glsl_permutation->program)
3738                 {
3739                         if (!r_glsl_permutation->compiled)
3740                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3741                         if (!r_glsl_permutation->program)
3742                         {
3743                                 // remove features until we find a valid permutation
3744                                 int i;
3745                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3746                                 {
3747                                         // reduce i more quickly whenever it would not remove any bits
3748                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3749                                         if (!(permutation & j))
3750                                                 continue;
3751                                         permutation -= j;
3752                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3753                                         if (!r_glsl_permutation->compiled)
3754                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3755                                         if (r_glsl_permutation->program)
3756                                                 break;
3757                                 }
3758                                 if (i >= SHADERPERMUTATION_COUNT)
3759                                 {
3760                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3761                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3762                                         qglUseProgramObjectARB(0);CHECKGLERROR
3763                                         return; // no bit left to clear, entire mode is broken
3764                                 }
3765                         }
3766                 }
3767                 CHECKGLERROR
3768                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3769         }
3770         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3771         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3772         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3773 }
3774
3775 #ifdef SUPPORTCG
3776 #include <Cg/cgGL.h>
3777 struct r_cg_permutation_s;
3778 typedef struct r_cg_permutation_s
3779 {
3780         /// hash lookup data
3781         struct r_cg_permutation_s *hashnext;
3782         unsigned int mode;
3783         unsigned int permutation;
3784
3785         /// indicates if we have tried compiling this permutation already
3786         qboolean compiled;
3787         /// 0 if compilation failed
3788         CGprogram vprogram;
3789         CGprogram fprogram;
3790         /// locations of detected parameters in programs, or NULL if not found
3791         CGparameter vp_EyePosition;
3792         CGparameter vp_FogPlane;
3793         CGparameter vp_LightDir;
3794         CGparameter vp_LightPosition;
3795         CGparameter vp_ModelToLight;
3796         CGparameter vp_TexMatrix;
3797         CGparameter vp_BackgroundTexMatrix;
3798         CGparameter vp_ModelViewProjectionMatrix;
3799         CGparameter vp_ModelViewMatrix;
3800         CGparameter vp_ShadowMapMatrix;
3801
3802         CGparameter fp_Texture_First;
3803         CGparameter fp_Texture_Second;
3804         CGparameter fp_Texture_GammaRamps;
3805         CGparameter fp_Texture_Normal;
3806         CGparameter fp_Texture_Color;
3807         CGparameter fp_Texture_Gloss;
3808         CGparameter fp_Texture_Glow;
3809         CGparameter fp_Texture_SecondaryNormal;
3810         CGparameter fp_Texture_SecondaryColor;
3811         CGparameter fp_Texture_SecondaryGloss;
3812         CGparameter fp_Texture_SecondaryGlow;
3813         CGparameter fp_Texture_Pants;
3814         CGparameter fp_Texture_Shirt;
3815         CGparameter fp_Texture_FogMask;
3816         CGparameter fp_Texture_Lightmap;
3817         CGparameter fp_Texture_Deluxemap;
3818         CGparameter fp_Texture_Attenuation;
3819         CGparameter fp_Texture_Cube;
3820         CGparameter fp_Texture_Refraction;
3821         CGparameter fp_Texture_Reflection;
3822         CGparameter fp_Texture_ShadowMapRect;
3823         CGparameter fp_Texture_ShadowMapCube;
3824         CGparameter fp_Texture_ShadowMap2D;
3825         CGparameter fp_Texture_CubeProjection;
3826         CGparameter fp_Texture_ScreenDepth;
3827         CGparameter fp_Texture_ScreenNormalMap;
3828         CGparameter fp_Texture_ScreenDiffuse;
3829         CGparameter fp_Texture_ScreenSpecular;
3830         CGparameter fp_Texture_ReflectMask;
3831         CGparameter fp_Texture_ReflectCube;
3832         CGparameter fp_Alpha;
3833         CGparameter fp_BloomBlur_Parameters;
3834         CGparameter fp_ClientTime;
3835         CGparameter fp_Color_Ambient;
3836         CGparameter fp_Color_Diffuse;
3837         CGparameter fp_Color_Specular;
3838         CGparameter fp_Color_Glow;
3839         CGparameter fp_Color_Pants;
3840         CGparameter fp_Color_Shirt;
3841         CGparameter fp_DeferredColor_Ambient;
3842         CGparameter fp_DeferredColor_Diffuse;
3843         CGparameter fp_DeferredColor_Specular;
3844         CGparameter fp_DeferredMod_Diffuse;
3845         CGparameter fp_DeferredMod_Specular;
3846         CGparameter fp_DistortScaleRefractReflect;
3847         CGparameter fp_EyePosition;
3848         CGparameter fp_FogColor;
3849         CGparameter fp_FogHeightFade;
3850         CGparameter fp_FogPlane;
3851         CGparameter fp_FogPlaneViewDist;
3852         CGparameter fp_FogRangeRecip;
3853         CGparameter fp_LightColor;
3854         CGparameter fp_LightDir;
3855         CGparameter fp_LightPosition;
3856         CGparameter fp_OffsetMapping_Scale;
3857         CGparameter fp_PixelSize;
3858         CGparameter fp_ReflectColor;
3859         CGparameter fp_ReflectFactor;
3860         CGparameter fp_ReflectOffset;
3861         CGparameter fp_RefractColor;
3862         CGparameter fp_Saturation;
3863         CGparameter fp_ScreenCenterRefractReflect;
3864         CGparameter fp_ScreenScaleRefractReflect;
3865         CGparameter fp_ScreenToDepth;
3866         CGparameter fp_ShadowMap_Parameters;
3867         CGparameter fp_ShadowMap_TextureScale;
3868         CGparameter fp_SpecularPower;
3869         CGparameter fp_UserVec1;
3870         CGparameter fp_UserVec2;
3871         CGparameter fp_UserVec3;
3872         CGparameter fp_UserVec4;
3873         CGparameter fp_ViewTintColor;
3874         CGparameter fp_ViewToLight;
3875         CGparameter fp_PixelToScreenTexCoord;
3876         CGparameter fp_ModelToReflectCube;
3877 }
3878 r_cg_permutation_t;
3879
3880 /// information about each possible shader permutation
3881 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3882 /// currently selected permutation
3883 r_cg_permutation_t *r_cg_permutation;
3884 /// storage for permutations linked in the hash table
3885 memexpandablearray_t r_cg_permutationarray;
3886
3887 #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));}}
3888
3889 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3890 {
3891         //unsigned int hashdepth = 0;
3892         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3893         r_cg_permutation_t *p;
3894         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3895         {
3896                 if (p->mode == mode && p->permutation == permutation)
3897                 {
3898                         //if (hashdepth > 10)
3899                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3900                         return p;
3901                 }
3902                 //hashdepth++;
3903         }
3904         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3905         p->mode = mode;
3906         p->permutation = permutation;
3907         p->hashnext = r_cg_permutationhash[mode][hashindex];
3908         r_cg_permutationhash[mode][hashindex] = p;
3909         //if (hashdepth > 10)
3910         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3911         return p;
3912 }
3913
3914 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3915 {
3916         char *shaderstring;
3917         if (!filename || !filename[0])
3918                 return NULL;
3919         if (!strcmp(filename, "cg/default.cg"))
3920         {
3921                 if (!cgshaderstring)
3922                 {
3923                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3924                         if (cgshaderstring)
3925                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3926                         else
3927                                 cgshaderstring = (char *)builtincgshaderstring;
3928                 }
3929                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
3930                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
3931                 return shaderstring;
3932         }
3933         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3934         if (shaderstring)
3935         {
3936                 if (printfromdisknotice)
3937                         Con_DPrintf("from disk %s... ", filename);
3938                 return shaderstring;
3939         }
3940         return shaderstring;
3941 }
3942
3943 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
3944 {
3945         // TODO: load or create .fp and .vp shader files
3946 }
3947
3948 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
3949 {
3950         int i;
3951         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
3952         int vertstrings_count = 0, vertstring_length = 0;
3953         int geomstrings_count = 0, geomstring_length = 0;
3954         int fragstrings_count = 0, fragstring_length = 0;
3955         char *t;
3956         char *vertexstring, *geometrystring, *fragmentstring;
3957         char *vertstring, *geomstring, *fragstring;
3958         const char *vertstrings_list[32+3];
3959         const char *geomstrings_list[32+3];
3960         const char *fragstrings_list[32+3];
3961         char permutationname[256];
3962         char cachename[256];
3963         CGprofile vertexProfile;
3964         CGprofile fragmentProfile;
3965
3966         if (p->compiled)
3967                 return;
3968         p->compiled = true;
3969         p->vprogram = NULL;
3970         p->fprogram = NULL;
3971
3972         permutationname[0] = 0;
3973         cachename[0] = 0;
3974         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
3975         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
3976         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
3977
3978         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3979         strlcat(cachename, "cg/", sizeof(cachename));
3980
3981         // the first pretext is which type of shader to compile as
3982         // (later these will all be bound together as a program object)
3983         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3984         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3985         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3986
3987         // the second pretext is the mode (for example a light source)
3988         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3989         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3990         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3991         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3992         strlcat(cachename, modeinfo->name, sizeof(cachename));
3993
3994         // now add all the permutation pretexts
3995         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3996         {
3997                 if (permutation & (1<<i))
3998                 {
3999                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4000                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4001                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4002                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4003                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4004                 }
4005                 else
4006                 {
4007                         // keep line numbers correct
4008                         vertstrings_list[vertstrings_count++] = "\n";
4009                         geomstrings_list[geomstrings_count++] = "\n";
4010                         fragstrings_list[fragstrings_count++] = "\n";
4011                 }
4012         }
4013
4014         // replace spaces in the cachename with _ characters
4015         for (i = 0;cachename[i];i++)
4016                 if (cachename[i] == ' ')
4017                         cachename[i] = '_';
4018
4019         // now append the shader text itself
4020         vertstrings_list[vertstrings_count++] = vertexstring;
4021         geomstrings_list[geomstrings_count++] = geometrystring;
4022         fragstrings_list[fragstrings_count++] = fragmentstring;
4023
4024         // if any sources were NULL, clear the respective list
4025         if (!vertexstring)
4026                 vertstrings_count = 0;
4027         if (!geometrystring)
4028                 geomstrings_count = 0;
4029         if (!fragmentstring)
4030                 fragstrings_count = 0;
4031
4032         vertstring_length = 0;
4033         for (i = 0;i < vertstrings_count;i++)
4034                 vertstring_length += strlen(vertstrings_list[i]);
4035         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4036         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4037                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4038
4039         geomstring_length = 0;
4040         for (i = 0;i < geomstrings_count;i++)
4041                 geomstring_length += strlen(geomstrings_list[i]);
4042         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4043         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4044                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4045
4046         fragstring_length = 0;
4047         for (i = 0;i < fragstrings_count;i++)
4048                 fragstring_length += strlen(fragstrings_list[i]);
4049         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4050         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4051                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4052
4053         CHECKGLERROR
4054         CHECKCGERROR
4055         //vertexProfile = CG_PROFILE_ARBVP1;
4056         //fragmentProfile = CG_PROFILE_ARBFP1;
4057         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4058         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4059         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4060         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4061         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4062         CHECKGLERROR
4063
4064         // try to load the cached shader, or generate one
4065         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4066
4067         // if caching failed, do a dynamic compile for now
4068         CHECKCGERROR
4069         if (vertstring[0] && !p->vprogram)
4070                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4071         CHECKCGERROR
4072         if (fragstring[0] && !p->fprogram)
4073                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4074         CHECKCGERROR
4075
4076         // look up all the uniform variable names we care about, so we don't
4077         // have to look them up every time we set them
4078         if (p->vprogram)
4079         {
4080                 CHECKCGERROR
4081                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4082                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4083                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4084                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4085                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4086                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4087                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4088                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4089                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4090                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4091                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4092                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4093                 CHECKCGERROR
4094         }
4095         if (p->fprogram)
4096         {
4097                 CHECKCGERROR
4098                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4099                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4100                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4101                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4102                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4103                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4104                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4105                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4106                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4107                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4108                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4109                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4110                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4111                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4112                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4113                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4114                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4115                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4116                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4117                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4118                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4119                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4120                 p->fp_Texture_ShadowMapRect      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
4121                 p->fp_Texture_ShadowMapCube      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
4122                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4123                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4124                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4125                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4126                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4127                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4128                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4129                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4130                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4131                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4132                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4133                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4134                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4135                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4136                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4137                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4138                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4139                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4140                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4141                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4142                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4143                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4144                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4145                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4146                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4147                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4148                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4149                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4150                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4151                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4152                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4153                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4154                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4155                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4156                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4157                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4158                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4159                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4160                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4161                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4162                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4163                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4164                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4165                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4166                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4167                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4168                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4169                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4170                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4171                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4172                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4173                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4174                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4175                 CHECKCGERROR
4176         }
4177
4178         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4179                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4180         else
4181                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4182
4183         // free the strings
4184         if (vertstring)
4185                 Mem_Free(vertstring);
4186         if (geomstring)
4187                 Mem_Free(geomstring);
4188         if (fragstring)
4189                 Mem_Free(fragstring);
4190         if (vertexstring)
4191                 Mem_Free(vertexstring);
4192         if (geometrystring)
4193                 Mem_Free(geometrystring);
4194         if (fragmentstring)
4195                 Mem_Free(fragmentstring);
4196 }
4197
4198 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4199 {
4200         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4201         CHECKGLERROR
4202         CHECKCGERROR
4203         if (r_cg_permutation != perm)
4204         {
4205                 r_cg_permutation = perm;
4206                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4207                 {
4208                         if (!r_cg_permutation->compiled)
4209                                 R_CG_CompilePermutation(perm, mode, permutation);
4210                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4211                         {
4212                                 // remove features until we find a valid permutation
4213                                 int i;
4214                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4215                                 {
4216                                         // reduce i more quickly whenever it would not remove any bits
4217                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4218                                         if (!(permutation & j))
4219                                                 continue;
4220                                         permutation -= j;
4221                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4222                                         if (!r_cg_permutation->compiled)
4223                                                 R_CG_CompilePermutation(perm, mode, permutation);
4224                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4225                                                 break;
4226                                 }
4227                                 if (i >= SHADERPERMUTATION_COUNT)
4228                                 {
4229                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4230                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4231                                         return; // no bit left to clear, entire mode is broken
4232                                 }
4233                         }
4234                 }
4235                 CHECKGLERROR
4236                 CHECKCGERROR
4237                 if (r_cg_permutation->vprogram)
4238                 {
4239                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4240                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4241                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4242                 }
4243                 else
4244                 {
4245                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4246                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4247                 }
4248                 if (r_cg_permutation->fprogram)
4249                 {
4250                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4251                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4252                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4253                 }
4254                 else
4255                 {
4256                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4257                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4258                 }
4259         }
4260         CHECKCGERROR
4261         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4262         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4263         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4264 }
4265
4266 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4267 {
4268         cgGLSetTextureParameter(param, R_GetTexture(tex));
4269         cgGLEnableTextureParameter(param);
4270 }
4271 #endif
4272
4273 void R_GLSL_Restart_f(void)
4274 {
4275         unsigned int i, limit;
4276         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4277                 Mem_Free(glslshaderstring);
4278         glslshaderstring = NULL;
4279         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4280                 Mem_Free(cgshaderstring);
4281         cgshaderstring = NULL;
4282         switch(vid.renderpath)
4283         {
4284         case RENDERPATH_GL20:
4285                 {
4286                         r_glsl_permutation_t *p;
4287                         r_glsl_permutation = NULL;
4288                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4289                         for (i = 0;i < limit;i++)
4290                         {
4291                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4292                                 {
4293                                         GL_Backend_FreeProgram(p->program);
4294                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4295                                 }
4296                         }
4297                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4298                 }
4299                 break;
4300         case RENDERPATH_CGGL:
4301 #ifdef SUPPORTCG
4302                 {
4303                         r_cg_permutation_t *p;
4304                         r_cg_permutation = NULL;
4305                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4306                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4307                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4308                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4309                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4310                         for (i = 0;i < limit;i++)
4311                         {
4312                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4313                                 {
4314                                         if (p->vprogram)
4315                                                 cgDestroyProgram(p->vprogram);
4316                                         if (p->fprogram)
4317                                                 cgDestroyProgram(p->fprogram);
4318                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4319                                 }
4320                         }
4321                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4322                 }
4323                 break;
4324 #endif
4325         case RENDERPATH_GL13:
4326         case RENDERPATH_GL11:
4327                 break;
4328         }
4329 }
4330
4331 void R_GLSL_DumpShader_f(void)
4332 {
4333         int i;
4334         qfile_t *file;
4335
4336         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4337         if (file)
4338         {
4339                 FS_Print(file, "/* The engine may define the following macros:\n");
4340                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4341                 for (i = 0;i < SHADERMODE_COUNT;i++)
4342                         FS_Print(file, glslshadermodeinfo[i].pretext);
4343                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4344                         FS_Print(file, shaderpermutationinfo[i].pretext);
4345                 FS_Print(file, "*/\n");
4346                 FS_Print(file, builtinshaderstring);
4347                 FS_Close(file);
4348                 Con_Printf("glsl/default.glsl written\n");
4349         }
4350         else
4351                 Con_Printf("failed to write to glsl/default.glsl\n");
4352
4353 #ifdef SUPPORTCG
4354         file = FS_OpenRealFile("cg/default.cg", "w", false);
4355         if (file)
4356         {
4357                 FS_Print(file, "/* The engine may define the following macros:\n");
4358                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4359                 for (i = 0;i < SHADERMODE_COUNT;i++)
4360                         FS_Print(file, cgshadermodeinfo[i].pretext);
4361                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4362                         FS_Print(file, shaderpermutationinfo[i].pretext);
4363                 FS_Print(file, "*/\n");
4364                 FS_Print(file, builtincgshaderstring);
4365                 FS_Close(file);
4366                 Con_Printf("cg/default.cg written\n");
4367         }
4368         else
4369                 Con_Printf("failed to write to cg/default.cg\n");
4370 #endif
4371 }
4372
4373 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4374 {
4375         if (!second)
4376                 texturemode = GL_MODULATE;
4377         switch (vid.renderpath)
4378         {
4379         case RENDERPATH_GL20:
4380                 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))));
4381                 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
4382                 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, second);
4383                 break;
4384         case RENDERPATH_CGGL:
4385 #ifdef SUPPORTCG
4386                 CHECKCGERROR
4387                 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))));
4388                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4389                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4390 #endif
4391                 break;
4392         case RENDERPATH_GL13:
4393                 R_Mesh_TexBind(0, first );
4394                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4395                 R_Mesh_TexBind(1, second);
4396                 if (second)
4397                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4398                 break;
4399         case RENDERPATH_GL11:
4400                 R_Mesh_TexBind(0, first );
4401                 break;
4402         }
4403 }
4404
4405 void R_SetupShader_DepthOrShadow(void)
4406 {
4407         switch (vid.renderpath)
4408         {
4409         case RENDERPATH_GL20:
4410                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4411                 break;
4412         case RENDERPATH_CGGL:
4413 #ifdef SUPPORTCG
4414                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4415 #endif
4416                 break;
4417         case RENDERPATH_GL13:
4418                 R_Mesh_TexBind(0, 0);
4419                 R_Mesh_TexBind(1, 0);
4420                 break;
4421         case RENDERPATH_GL11:
4422                 R_Mesh_TexBind(0, 0);
4423                 break;
4424         }
4425 }
4426
4427 void R_SetupShader_ShowDepth(void)
4428 {
4429         switch (vid.renderpath)
4430         {
4431         case RENDERPATH_GL20:
4432                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4433                 break;
4434         case RENDERPATH_CGGL:
4435 #ifdef SUPPORTCG
4436                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4437 #endif
4438                 break;
4439         case RENDERPATH_GL13:
4440                 break;
4441         case RENDERPATH_GL11:
4442                 break;
4443         }
4444 }
4445
4446 extern qboolean r_shadow_usingdeferredprepass;
4447 extern cvar_t r_shadow_deferred_8bitrange;
4448 extern rtexture_t *r_shadow_attenuationgradienttexture;
4449 extern rtexture_t *r_shadow_attenuation2dtexture;
4450 extern rtexture_t *r_shadow_attenuation3dtexture;
4451 extern qboolean r_shadow_usingshadowmaprect;
4452 extern qboolean r_shadow_usingshadowmapcube;
4453 extern qboolean r_shadow_usingshadowmap2d;
4454 extern qboolean r_shadow_usingshadowmaportho;
4455 extern float r_shadow_shadowmap_texturescale[2];
4456 extern float r_shadow_shadowmap_parameters[4];
4457 extern qboolean r_shadow_shadowmapvsdct;
4458 extern qboolean r_shadow_shadowmapsampler;
4459 extern int r_shadow_shadowmappcf;
4460 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4461 extern rtexture_t *r_shadow_shadowmap2dtexture;
4462 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4463 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4464 extern matrix4x4_t r_shadow_shadowmapmatrix;
4465 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4466 extern int r_shadow_prepass_width;
4467 extern int r_shadow_prepass_height;
4468 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4469 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4470 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4471 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4472 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
4473 {
4474         // select a permutation of the lighting shader appropriate to this
4475         // combination of texture, entity, light source, and fogging, only use the
4476         // minimum features necessary to avoid wasting rendering time in the
4477         // fragment shader on features that are not being used
4478         unsigned int permutation = 0;
4479         unsigned int mode = 0;
4480         float m16f[16];
4481         if (rsurfacepass == RSURFPASS_BACKGROUND)
4482         {
4483                 // distorted background
4484                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4485                         mode = SHADERMODE_WATER;
4486                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
4487                         mode = SHADERMODE_REFRACTION;
4488                 else
4489                 {
4490                         mode = SHADERMODE_GENERIC;
4491                         permutation |= SHADERPERMUTATION_DIFFUSE;
4492                 }
4493                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4494                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4495                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4496                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4497                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4498                 R_Mesh_ColorPointer(NULL, 0, 0);
4499                 GL_AlphaTest(false);
4500                 GL_BlendFunc(GL_ONE, GL_ZERO);
4501         }
4502         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4503         {
4504                 if (r_glsl_offsetmapping.integer)
4505                 {
4506                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4507                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4508                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4509                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4510                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4511                         {
4512                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4513                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4514                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4515                         }
4516                 }
4517                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4518                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4519                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4520                         permutation |= SHADERPERMUTATION_ALPHAKILL;
4521                 // normalmap (deferred prepass), may use alpha test on diffuse
4522                 mode = SHADERMODE_DEFERREDGEOMETRY;
4523                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4524                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4525                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4526                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4527                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4528                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4529                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4530                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4531                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4532                 else
4533                         R_Mesh_ColorPointer(NULL, 0, 0);
4534                 GL_AlphaTest(false);
4535                 GL_BlendFunc(GL_ONE, GL_ZERO);
4536         }
4537         else if (rsurfacepass == RSURFPASS_RTLIGHT)
4538         {
4539                 if (r_glsl_offsetmapping.integer)
4540                 {
4541                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4542                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4543                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4544                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4545                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4546                         {
4547                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4548                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4549                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4550                         }
4551                 }
4552                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4553                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4554                 // light source
4555                 mode = SHADERMODE_LIGHTSOURCE;
4556                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4557                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4558                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4559                         permutation |= SHADERPERMUTATION_CUBEFILTER;
4560                 if (diffusescale > 0)
4561                         permutation |= SHADERPERMUTATION_DIFFUSE;
4562                 if (specularscale > 0)
4563                 {
4564                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4565                         if (r_shadow_glossexact.integer)
4566                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4567                 }
4568                 if (r_refdef.fogenabled)
4569                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4570                 if (rsurface.texture->colormapping)
4571                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4572                 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4573                 {
4574                         if (r_shadow_usingshadowmaprect)
4575                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4576                         if (r_shadow_usingshadowmap2d)
4577                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4578                         if (r_shadow_usingshadowmapcube)
4579                                 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4580                         else if(r_shadow_shadowmapvsdct)
4581                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4582
4583                         if (r_shadow_shadowmapsampler)
4584                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4585                         if (r_shadow_shadowmappcf > 1)
4586                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4587                         else if (r_shadow_shadowmappcf)
4588                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4589                 }
4590                 if (rsurface.texture->reflectmasktexture)
4591                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4592                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4593                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4594                 {
4595                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4596                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4597                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4598                 }
4599                 else
4600                 {
4601                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4602                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4603                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4604                 }
4605                 //R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4606                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4607                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4608                 else
4609                         R_Mesh_ColorPointer(NULL, 0, 0);
4610                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4611                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4612         }
4613         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4614         {
4615                 if (r_glsl_offsetmapping.integer)
4616                 {
4617                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4618                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4619                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4620                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4621                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4622                         {
4623                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4624                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4625                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4626                         }
4627                 }
4628                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4629                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4630                 // unshaded geometry (fullbright or ambient model lighting)
4631                 mode = SHADERMODE_FLATCOLOR;
4632                 ambientscale = diffusescale = specularscale = 0;
4633                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4634                         permutation |= SHADERPERMUTATION_GLOW;
4635                 if (r_refdef.fogenabled)
4636                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4637                 if (rsurface.texture->colormapping)
4638                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4639                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4640                 {
4641                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4642                         if (r_shadow_usingshadowmaprect)
4643                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4644                         if (r_shadow_usingshadowmap2d)
4645                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4646
4647                         if (r_shadow_shadowmapsampler)
4648                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4649                         if (r_shadow_shadowmappcf > 1)
4650                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4651                         else if (r_shadow_shadowmappcf)
4652                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4653                 }
4654                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4655                         permutation |= SHADERPERMUTATION_REFLECTION;
4656                 if (rsurface.texture->reflectmasktexture)
4657                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4658                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4659                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4660                 {
4661                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4662                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4663                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4664                 }
4665                 else
4666                 {
4667                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4668                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4669                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4670                 }
4671                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4672                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4673                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4674                 else
4675                         R_Mesh_ColorPointer(NULL, 0, 0);
4676                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4677                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4678         }
4679         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4680         {
4681                 if (r_glsl_offsetmapping.integer)
4682                 {
4683                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4684                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4685                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4686                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4687                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4688                         {
4689                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4690                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4691                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4692                         }
4693                 }
4694                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4695                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4696                 // directional model lighting
4697                 mode = SHADERMODE_LIGHTDIRECTION;
4698                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4699                         permutation |= SHADERPERMUTATION_GLOW;
4700                 permutation |= SHADERPERMUTATION_DIFFUSE;
4701                 if (specularscale > 0)
4702                 {
4703                         permutation |= SHADERPERMUTATION_SPECULAR;
4704                         if (r_shadow_glossexact.integer)
4705                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4706                 }
4707                 if (r_refdef.fogenabled)
4708                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4709                 if (rsurface.texture->colormapping)
4710                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4711                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4712                 {
4713                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4714                         if (r_shadow_usingshadowmaprect)
4715                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4716                         if (r_shadow_usingshadowmap2d)
4717                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4718
4719                         if (r_shadow_shadowmapsampler)
4720                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4721                         if (r_shadow_shadowmappcf > 1)
4722                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4723                         else if (r_shadow_shadowmappcf)
4724                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4725                 }
4726                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4727                         permutation |= SHADERPERMUTATION_REFLECTION;
4728                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4729                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4730                 if (rsurface.texture->reflectmasktexture)
4731                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4732                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4733                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4734                 {
4735                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4736                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4737                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4738                 }
4739                 else
4740                 {
4741                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4742                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4743                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4744                 }
4745                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4746                 R_Mesh_ColorPointer(NULL, 0, 0);
4747                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4748                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4749         }
4750         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
4751         {
4752                 if (r_glsl_offsetmapping.integer)
4753                 {
4754                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4755                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4756                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4757                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4758                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4759                         {
4760                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4761                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4762                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4763                         }
4764                 }
4765                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4766                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4767                 // ambient model lighting
4768                 mode = SHADERMODE_LIGHTDIRECTION;
4769                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4770                         permutation |= SHADERPERMUTATION_GLOW;
4771                 if (r_refdef.fogenabled)
4772                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4773                 if (rsurface.texture->colormapping)
4774                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4775                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4776                 {
4777                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4778                         if (r_shadow_usingshadowmaprect)
4779                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4780                         if (r_shadow_usingshadowmap2d)
4781                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4782
4783                         if (r_shadow_shadowmapsampler)
4784                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4785                         if (r_shadow_shadowmappcf > 1)
4786                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4787                         else if (r_shadow_shadowmappcf)
4788                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4789                 }
4790                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4791                         permutation |= SHADERPERMUTATION_REFLECTION;
4792                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4793                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4794                 if (rsurface.texture->reflectmasktexture)
4795                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4796                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4797                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4798                 {
4799                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4800                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4801                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4802                 }
4803                 else
4804                 {
4805                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4806                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4807                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4808                 }
4809                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4810                 R_Mesh_ColorPointer(NULL, 0, 0);
4811                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4812                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4813         }
4814         else
4815         {
4816                 if (r_glsl_offsetmapping.integer)
4817                 {
4818                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4819                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4820                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4821                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4822                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4823                         {
4824                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4825                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4826                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4827                         }
4828                 }
4829                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4830                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4831                 // lightmapped wall
4832                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4833                         permutation |= SHADERPERMUTATION_GLOW;
4834                 if (r_refdef.fogenabled)
4835                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4836                 if (rsurface.texture->colormapping)
4837                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4838                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4839                 {
4840                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4841                         if (r_shadow_usingshadowmaprect)
4842                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4843                         if (r_shadow_usingshadowmap2d)
4844                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4845
4846                         if (r_shadow_shadowmapsampler)
4847                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4848                         if (r_shadow_shadowmappcf > 1)
4849                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4850                         else if (r_shadow_shadowmappcf)
4851                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4852                 }
4853                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4854                         permutation |= SHADERPERMUTATION_REFLECTION;
4855                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4856                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4857                 if (rsurface.texture->reflectmasktexture)
4858                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4859                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
4860                 {
4861                         // deluxemapping (light direction texture)
4862                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
4863                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
4864                         else
4865                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4866                         permutation |= SHADERPERMUTATION_DIFFUSE;
4867                         if (specularscale > 0)
4868                         {
4869                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4870                                 if (r_shadow_glossexact.integer)
4871                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4872                         }
4873                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4874                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4875                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4876                         else
4877                                 R_Mesh_ColorPointer(NULL, 0, 0);
4878                 }
4879                 else if (r_glsl_deluxemapping.integer >= 2)
4880                 {
4881                         // fake deluxemapping (uniform light direction in tangentspace)
4882                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4883                         permutation |= SHADERPERMUTATION_DIFFUSE;
4884                         if (specularscale > 0)
4885                         {
4886                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4887                                 if (r_shadow_glossexact.integer)
4888                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4889                         }
4890                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4891                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4892                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4893                         else
4894                                 R_Mesh_ColorPointer(NULL, 0, 0);
4895                 }
4896                 else if (rsurface.uselightmaptexture)
4897                 {
4898                         // ordinary lightmapping (q1bsp, q3bsp)
4899                         mode = SHADERMODE_LIGHTMAP;
4900                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4901                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4902                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4903                         else
4904                                 R_Mesh_ColorPointer(NULL, 0, 0);
4905                 }
4906                 else
4907                 {
4908                         // ordinary vertex coloring (q3bsp)
4909                         mode = SHADERMODE_VERTEXCOLOR;
4910                         R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4911                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4912                 }
4913                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4914                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4915                 {
4916                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4917                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4918                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4919                 }
4920                 else
4921                 {
4922                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4923                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4924                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4925                 }
4926                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4927                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4928         }
4929         switch(vid.renderpath)
4930         {
4931         case RENDERPATH_GL20:
4932                 R_SetupShader_SetPermutationGLSL(mode, permutation);
4933                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
4934                 if (mode == SHADERMODE_LIGHTSOURCE)
4935                 {
4936                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
4937                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
4938                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
4939                         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);
4940                         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);
4941                         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);
4942         
4943                         // additive passes are only darkened by fog, not tinted
4944                         if (r_glsl_permutation->loc_FogColor >= 0)
4945                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4946                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4947                 }
4948                 else
4949                 {
4950                         if (mode == SHADERMODE_FLATCOLOR)
4951                         {
4952                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
4953                         }
4954                         else if (mode == SHADERMODE_LIGHTDIRECTION)
4955                         {
4956                                 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]);
4957                                 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]);
4958                                 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);
4959                                 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);
4960                                 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);
4961                                 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]);
4962                                 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]);
4963                         }
4964                         else
4965                         {
4966                                 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]);
4967                                 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]);
4968                                 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);
4969                                 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);
4970                                 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);
4971                         }
4972                         // additive passes are only darkened by fog, not tinted
4973                         if (r_glsl_permutation->loc_FogColor >= 0)
4974                         {
4975                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4976                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4977                                 else
4978                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4979                         }
4980                         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);
4981                         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]);
4982                         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]);
4983                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
4984                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
4985                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
4986                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
4987                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4988                 }
4989                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
4990                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
4991                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
4992                 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]);
4993                 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]);
4994
4995                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
4996                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
4997                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
4998                 if (r_glsl_permutation->loc_Color_Pants >= 0)
4999                 {
5000                         if (rsurface.texture->pantstexture)
5001                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5002                         else
5003                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5004                 }
5005                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5006                 {
5007                         if (rsurface.texture->shirttexture)
5008                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5009                         else
5010                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5011                 }
5012                 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]);
5013                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5014                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5015                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5016                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5017                 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]);
5018                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5019
5020         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
5021         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
5022         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
5023                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5024                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5025                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5026                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5027                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5028                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5029                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5030                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5031                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5032                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5033                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5034                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5035                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5036                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_white                                     );
5037                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_blanknormalmap                            );
5038                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5039                 if (r_glsl_permutation->loc_Texture_Refraction      >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , r_texture_white                                     );
5040                 if (r_glsl_permutation->loc_Texture_Reflection      >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , r_texture_white                                     );
5041                 if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5042                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5043                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5044                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5045                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5046                 {
5047                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
5048                         if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT, r_shadow_shadowmaprectangletexture                  );
5049                         if (rsurface.rtlight)
5050                         {
5051                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5052                                 if (r_shadow_usingshadowmapcube)
5053                                         if (r_glsl_permutation->loc_Texture_ShadowMapCube   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE     , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5054                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5055                         }
5056                 }
5057                 CHECKGLERROR
5058                 break;
5059         case RENDERPATH_CGGL:
5060 #ifdef SUPPORTCG
5061                 R_SetupShader_SetPermutationCG(mode, permutation);
5062                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
5063                 if (mode == SHADERMODE_LIGHTSOURCE)
5064                 {
5065                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
5066                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5067                 }
5068                 else
5069                 {
5070                         if (mode == SHADERMODE_LIGHTDIRECTION)
5071                         {
5072                                 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
5073                         }
5074                 }
5075                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
5076                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
5077                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
5078                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5079                 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
5080                 CHECKGLERROR
5081
5082                 if (mode == SHADERMODE_LIGHTSOURCE)
5083                 {
5084                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5085                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
5086                         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
5087                         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
5088                         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
5089
5090                         // additive passes are only darkened by fog, not tinted
5091                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
5092                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5093                 }
5094                 else
5095                 {
5096                         if (mode == SHADERMODE_FLATCOLOR)
5097                         {
5098                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);CHECKCGERROR
5099                         }
5100                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5101                         {
5102                                 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
5103                                 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
5104                                 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
5105                                 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
5106                                 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
5107                                 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
5108                                 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
5109                         }
5110                         else
5111                         {
5112                                 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
5113                                 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
5114                                 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
5115                                 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
5116                                 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
5117                         }
5118                         // additive passes are only darkened by fog, not tinted
5119                         if (r_cg_permutation->fp_FogColor)
5120                         {
5121                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5122                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
5123                                 else
5124                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5125                                 CHECKCGERROR
5126                         }
5127                         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
5128                         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
5129                         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
5130                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
5131                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
5132                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
5133                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
5134                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5135                 }
5136                 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
5137                 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
5138                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
5139                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
5140                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5141                 if (r_cg_permutation->fp_Color_Pants)
5142                 {
5143                         if (rsurface.texture->pantstexture)
5144                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5145                         else
5146                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
5147                         CHECKCGERROR
5148                 }
5149                 if (r_cg_permutation->fp_Color_Shirt)
5150                 {
5151                         if (rsurface.texture->shirttexture)
5152                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5153                         else
5154                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
5155                         CHECKCGERROR
5156                 }
5157                 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
5158                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
5159                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
5160                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
5161                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
5162                 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
5163                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5164
5165         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
5166         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
5167         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
5168                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
5169                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
5170                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
5171                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
5172                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
5173                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
5174                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
5175                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
5176                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
5177                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
5178                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
5179                 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
5180                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
5181                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , r_texture_white                                     );CHECKCGERROR
5182                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , r_texture_blanknormalmap                            );CHECKCGERROR
5183                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
5184                 if (r_cg_permutation->fp_Texture_Refraction     ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction     , r_texture_white                                     );CHECKCGERROR
5185                 if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , r_texture_white                                     );CHECKCGERROR
5186                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
5187                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
5188                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
5189                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
5190                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5191                 {
5192                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5193                         if (r_cg_permutation->fp_Texture_ShadowMapRect  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
5194                         if (rsurface.rtlight)
5195                         {
5196                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
5197                                 if (r_shadow_usingshadowmapcube)
5198                                         if (r_cg_permutation->fp_Texture_ShadowMapCube  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5199                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
5200                         }
5201                 }
5202
5203                 CHECKGLERROR
5204 #endif
5205                 break;
5206         case RENDERPATH_GL13:
5207         case RENDERPATH_GL11:
5208                 break;
5209         }
5210 }
5211
5212 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
5213 {
5214         // select a permutation of the lighting shader appropriate to this
5215         // combination of texture, entity, light source, and fogging, only use the
5216         // minimum features necessary to avoid wasting rendering time in the
5217         // fragment shader on features that are not being used
5218         unsigned int permutation = 0;
5219         unsigned int mode = 0;
5220         const float *lightcolorbase = rtlight->currentcolor;
5221         float ambientscale = rtlight->ambientscale;
5222         float diffusescale = rtlight->diffusescale;
5223         float specularscale = rtlight->specularscale;
5224         // this is the location of the light in view space
5225         vec3_t viewlightorigin;
5226         // this transforms from view space (camera) to light space (cubemap)
5227         matrix4x4_t viewtolight;
5228         matrix4x4_t lighttoview;
5229         float viewtolight16f[16];
5230         float range = 1.0f / r_shadow_deferred_8bitrange.value;
5231         // light source
5232         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
5233         if (rtlight->currentcubemap != r_texture_whitecube)
5234                 permutation |= SHADERPERMUTATION_CUBEFILTER;
5235         if (diffusescale > 0)
5236                 permutation |= SHADERPERMUTATION_DIFFUSE;
5237         if (specularscale > 0)
5238         {
5239                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5240                 if (r_shadow_glossexact.integer)
5241                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5242         }
5243         if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
5244         {
5245                 if (r_shadow_usingshadowmaprect)
5246                         permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5247                 if (r_shadow_usingshadowmap2d)
5248                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5249                 if (r_shadow_usingshadowmapcube)
5250                         permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
5251                 else if(r_shadow_shadowmapvsdct)
5252                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5253
5254                 if (r_shadow_shadowmapsampler)
5255                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5256                 if (r_shadow_shadowmappcf > 1)
5257                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5258                 else if (r_shadow_shadowmappcf)
5259                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5260         }
5261         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
5262         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
5263         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
5264         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
5265         switch(vid.renderpath)
5266         {
5267         case RENDERPATH_GL20:
5268                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5269                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5270                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
5271                 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);
5272                 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);
5273                 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);
5274                 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]);
5275                 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]);
5276                 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));
5277                 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]);
5278                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5279
5280                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
5281                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
5282                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
5283                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
5284                 if (r_glsl_permutation->loc_Texture_ShadowMapRect     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT      , r_shadow_shadowmaprectangletexture                  );
5285                 if (r_shadow_usingshadowmapcube)
5286                         if (r_glsl_permutation->loc_Texture_ShadowMapCube     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE      , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5287                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
5288                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
5289                 break;
5290         case RENDERPATH_CGGL:
5291 #ifdef SUPPORTCG
5292                 R_SetupShader_SetPermutationCG(mode, permutation);
5293                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
5294                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
5295                 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
5296                 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
5297                 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
5298                 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
5299                 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
5300                 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
5301                 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
5302                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5303
5304                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
5305                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
5306                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
5307                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
5308                 if (r_cg_permutation->fp_Texture_ShadowMapRect    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
5309                 if (r_shadow_usingshadowmapcube)
5310                         if (r_cg_permutation->fp_Texture_ShadowMapCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5311                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5312                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
5313 #endif
5314                 break;
5315         case RENDERPATH_GL13:
5316         case RENDERPATH_GL11:
5317                 break;
5318         }
5319 }
5320
5321 #define SKINFRAME_HASH 1024
5322
5323 typedef struct
5324 {
5325         int loadsequence; // incremented each level change
5326         memexpandablearray_t array;
5327         skinframe_t *hash[SKINFRAME_HASH];
5328 }
5329 r_skinframe_t;
5330 r_skinframe_t r_skinframe;
5331
5332 void R_SkinFrame_PrepareForPurge(void)
5333 {
5334         r_skinframe.loadsequence++;
5335         // wrap it without hitting zero
5336         if (r_skinframe.loadsequence >= 200)
5337                 r_skinframe.loadsequence = 1;
5338 }
5339
5340 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5341 {
5342         if (!skinframe)
5343                 return;
5344         // mark the skinframe as used for the purging code
5345         skinframe->loadsequence = r_skinframe.loadsequence;
5346 }
5347
5348 void R_SkinFrame_Purge(void)
5349 {
5350         int i;
5351         skinframe_t *s;
5352         for (i = 0;i < SKINFRAME_HASH;i++)
5353         {
5354                 for (s = r_skinframe.hash[i];s;s = s->next)
5355                 {
5356                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5357                         {
5358                                 if (s->merged == s->base)
5359                                         s->merged = NULL;
5360                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5361                                 R_PurgeTexture(s->stain );s->stain  = NULL;
5362                                 R_PurgeTexture(s->merged);s->merged = NULL;
5363                                 R_PurgeTexture(s->base  );s->base   = NULL;
5364                                 R_PurgeTexture(s->pants );s->pants  = NULL;
5365                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
5366                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
5367                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
5368                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
5369                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
5370                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
5371                                 s->loadsequence = 0;
5372                         }
5373                 }
5374         }
5375 }
5376
5377 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5378         skinframe_t *item;
5379         char basename[MAX_QPATH];
5380
5381         Image_StripImageExtension(name, basename, sizeof(basename));
5382
5383         if( last == NULL ) {
5384                 int hashindex;
5385                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5386                 item = r_skinframe.hash[hashindex];
5387         } else {
5388                 item = last->next;
5389         }
5390
5391         // linearly search through the hash bucket
5392         for( ; item ; item = item->next ) {
5393                 if( !strcmp( item->basename, basename ) ) {
5394                         return item;
5395                 }
5396         }
5397         return NULL;
5398 }
5399
5400 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5401 {
5402         skinframe_t *item;
5403         int hashindex;
5404         char basename[MAX_QPATH];
5405
5406         Image_StripImageExtension(name, basename, sizeof(basename));
5407
5408         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5409         for (item = r_skinframe.hash[hashindex];item;item = item->next)
5410                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5411                         break;
5412
5413         if (!item) {
5414                 rtexture_t *dyntexture;
5415                 // check whether its a dynamic texture
5416                 dyntexture = CL_GetDynTexture( basename );
5417                 if (!add && !dyntexture)
5418                         return NULL;
5419                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5420                 memset(item, 0, sizeof(*item));
5421                 strlcpy(item->basename, basename, sizeof(item->basename));
5422                 item->base = dyntexture; // either NULL or dyntexture handle
5423                 item->textureflags = textureflags;
5424                 item->comparewidth = comparewidth;
5425                 item->compareheight = compareheight;
5426                 item->comparecrc = comparecrc;
5427                 item->next = r_skinframe.hash[hashindex];
5428                 r_skinframe.hash[hashindex] = item;
5429         }
5430         else if( item->base == NULL )
5431         {
5432                 rtexture_t *dyntexture;
5433                 // check whether its a dynamic texture
5434                 // 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]
5435                 dyntexture = CL_GetDynTexture( basename );
5436                 item->base = dyntexture; // either NULL or dyntexture handle
5437         }
5438
5439         R_SkinFrame_MarkUsed(item);
5440         return item;
5441 }
5442
5443 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5444         { \
5445                 unsigned long long avgcolor[5], wsum; \
5446                 int pix, comp, w; \
5447                 avgcolor[0] = 0; \
5448                 avgcolor[1] = 0; \
5449                 avgcolor[2] = 0; \
5450                 avgcolor[3] = 0; \
5451                 avgcolor[4] = 0; \
5452                 wsum = 0; \
5453                 for(pix = 0; pix < cnt; ++pix) \
5454                 { \
5455                         w = 0; \
5456                         for(comp = 0; comp < 3; ++comp) \
5457                                 w += getpixel; \
5458                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5459                         { \
5460                                 ++wsum; \
5461                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5462                                 w = getpixel; \
5463                                 for(comp = 0; comp < 3; ++comp) \
5464                                         avgcolor[comp] += getpixel * w; \
5465                                 avgcolor[3] += w; \
5466                         } \
5467                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5468                         avgcolor[4] += getpixel; \
5469                 } \
5470                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5471                         avgcolor[3] = 1; \
5472                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5473                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5474                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5475                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5476         }
5477
5478 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5479 {
5480         int j;
5481         unsigned char *pixels;
5482         unsigned char *bumppixels;
5483         unsigned char *basepixels = NULL;
5484         int basepixels_width = 0;
5485         int basepixels_height = 0;
5486         skinframe_t *skinframe;
5487         rtexture_t *ddsbase = NULL;
5488         qboolean ddshasalpha = false;
5489         float ddsavgcolor[4];
5490         char basename[MAX_QPATH];
5491
5492         if (cls.state == ca_dedicated)
5493                 return NULL;
5494
5495         // return an existing skinframe if already loaded
5496         // if loading of the first image fails, don't make a new skinframe as it
5497         // would cause all future lookups of this to be missing
5498         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5499         if (skinframe && skinframe->base)
5500                 return skinframe;
5501
5502         Image_StripImageExtension(name, basename, sizeof(basename));
5503
5504         // check for DDS texture file first
5505         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor)))
5506         {
5507                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer);
5508                 if (basepixels == NULL)
5509                         return NULL;
5510         }
5511
5512         if (developer_loading.integer)
5513                 Con_Printf("loading skin \"%s\"\n", name);
5514
5515         // we've got some pixels to store, so really allocate this new texture now
5516         if (!skinframe)
5517                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5518         skinframe->stain = NULL;
5519         skinframe->merged = NULL;
5520         skinframe->base = NULL;
5521         skinframe->pants = NULL;
5522         skinframe->shirt = NULL;
5523         skinframe->nmap = NULL;
5524         skinframe->gloss = NULL;
5525         skinframe->glow = NULL;
5526         skinframe->fog = NULL;
5527         skinframe->reflect = NULL;
5528         skinframe->hasalpha = false;
5529
5530         if (ddsbase)
5531         {
5532                 skinframe->base = ddsbase;
5533                 skinframe->hasalpha = ddshasalpha;
5534                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5535                 if (r_loadfog && skinframe->hasalpha)
5536                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5537                 //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]);
5538         }
5539         else
5540         {
5541                 basepixels_width = image_width;
5542                 basepixels_height = image_height;
5543                 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);
5544                 if (textureflags & TEXF_ALPHA)
5545                 {
5546                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5547                         {
5548                                 if (basepixels[j] < 255)
5549                                 {
5550                                         skinframe->hasalpha = true;
5551                                         break;
5552                                 }
5553                         }
5554                         if (r_loadfog && skinframe->hasalpha)
5555                         {
5556                                 // has transparent pixels
5557                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5558                                 for (j = 0;j < image_width * image_height * 4;j += 4)
5559                                 {
5560                                         pixels[j+0] = 255;
5561                                         pixels[j+1] = 255;
5562                                         pixels[j+2] = 255;
5563                                         pixels[j+3] = basepixels[j+3];
5564                                 }
5565                                 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);
5566                                 Mem_Free(pixels);
5567                         }
5568                 }
5569                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5570                 //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]);
5571                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5572                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true);
5573                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
5574                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true);
5575         }
5576
5577         if (r_loaddds)
5578         {
5579                 if (r_loadnormalmap)
5580                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5581                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL);
5582                 if (r_loadgloss)
5583                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL);
5584                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL);
5585                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL);
5586                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL);
5587         }
5588
5589         // _norm is the name used by tenebrae and has been adopted as standard
5590         if (r_loadnormalmap && skinframe->nmap == NULL)
5591         {
5592                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false)) != NULL)
5593                 {
5594                         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);
5595                         Mem_Free(pixels);
5596                         pixels = NULL;
5597                 }
5598                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false)) != NULL)
5599                 {
5600                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5601                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5602                         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);
5603                         Mem_Free(pixels);
5604                         Mem_Free(bumppixels);
5605                 }
5606                 else if (r_shadow_bumpscale_basetexture.value > 0)
5607                 {
5608                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5609                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5610                         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);
5611                         Mem_Free(pixels);
5612                 }
5613                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
5614                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true);
5615         }
5616
5617         // _luma is supported only for tenebrae compatibility
5618         // _glow is the preferred name
5619         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))))
5620         {
5621                 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);
5622                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
5623                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true);
5624                 Mem_Free(pixels);pixels = NULL;
5625         }
5626
5627         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5628         {
5629                 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);
5630                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
5631                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true);
5632                 Mem_Free(pixels);
5633                 pixels = NULL;
5634         }
5635
5636         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5637         {
5638                 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);
5639                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
5640                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true);
5641                 Mem_Free(pixels);
5642                 pixels = NULL;
5643         }
5644
5645         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5646         {
5647                 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);
5648                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
5649                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true);
5650                 Mem_Free(pixels);
5651                 pixels = NULL;
5652         }
5653
5654         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5655         {
5656                 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);
5657                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
5658                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true);
5659                 Mem_Free(pixels);
5660                 pixels = NULL;
5661         }
5662
5663         if (basepixels)
5664                 Mem_Free(basepixels);
5665
5666         return skinframe;
5667 }
5668
5669 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
5670 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
5671 {
5672         int i;
5673         unsigned char *temp1, *temp2;
5674         skinframe_t *skinframe;
5675
5676         if (cls.state == ca_dedicated)
5677                 return NULL;
5678
5679         // if already loaded just return it, otherwise make a new skinframe
5680         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
5681         if (skinframe && skinframe->base)
5682                 return skinframe;
5683
5684         skinframe->stain = NULL;
5685         skinframe->merged = NULL;
5686         skinframe->base = NULL;
5687         skinframe->pants = NULL;
5688         skinframe->shirt = NULL;
5689         skinframe->nmap = NULL;
5690         skinframe->gloss = NULL;
5691         skinframe->glow = NULL;
5692         skinframe->fog = NULL;
5693         skinframe->reflect = NULL;
5694         skinframe->hasalpha = false;
5695
5696         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5697         if (!skindata)
5698                 return NULL;
5699
5700         if (developer_loading.integer)
5701                 Con_Printf("loading 32bit skin \"%s\"\n", name);
5702
5703         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
5704         {
5705                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5706                 temp2 = temp1 + width * height * 4;
5707                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5708                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5709                 Mem_Free(temp1);
5710         }
5711         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5712         if (textureflags & TEXF_ALPHA)
5713         {
5714                 for (i = 3;i < width * height * 4;i += 4)
5715                 {
5716                         if (skindata[i] < 255)
5717                         {
5718                                 skinframe->hasalpha = true;
5719                                 break;
5720                         }
5721                 }
5722                 if (r_loadfog && skinframe->hasalpha)
5723                 {
5724                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
5725                         memcpy(fogpixels, skindata, width * height * 4);
5726                         for (i = 0;i < width * height * 4;i += 4)
5727                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
5728                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5729                         Mem_Free(fogpixels);
5730                 }
5731         }
5732
5733         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
5734         //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]);
5735
5736         return skinframe;
5737 }
5738
5739 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
5740 {
5741         int i;
5742         int featuresmask;
5743         skinframe_t *skinframe;
5744
5745         if (cls.state == ca_dedicated)
5746                 return NULL;
5747
5748         // if already loaded just return it, otherwise make a new skinframe
5749         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5750         if (skinframe && skinframe->base)
5751                 return skinframe;
5752
5753         skinframe->stain = NULL;
5754         skinframe->merged = NULL;
5755         skinframe->base = NULL;
5756         skinframe->pants = NULL;
5757         skinframe->shirt = NULL;
5758         skinframe->nmap = NULL;
5759         skinframe->gloss = NULL;
5760         skinframe->glow = NULL;
5761         skinframe->fog = NULL;
5762         skinframe->reflect = NULL;
5763         skinframe->hasalpha = false;
5764
5765         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5766         if (!skindata)
5767                 return NULL;
5768
5769         if (developer_loading.integer)
5770                 Con_Printf("loading quake skin \"%s\"\n", name);
5771
5772         // 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)
5773         skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
5774         memcpy(skinframe->qpixels, skindata, width*height);
5775         skinframe->qwidth = width;
5776         skinframe->qheight = height;
5777
5778         featuresmask = 0;
5779         for (i = 0;i < width * height;i++)
5780                 featuresmask |= palette_featureflags[skindata[i]];
5781
5782         skinframe->hasalpha = false;
5783         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
5784         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
5785         skinframe->qgeneratemerged = true;
5786         skinframe->qgeneratebase = skinframe->qhascolormapping;
5787         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
5788
5789         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
5790         //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]);
5791
5792         return skinframe;
5793 }
5794
5795 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
5796 {
5797         int width;
5798         int height;
5799         unsigned char *skindata;
5800
5801         if (!skinframe->qpixels)
5802                 return;
5803
5804         if (!skinframe->qhascolormapping)
5805                 colormapped = false;
5806
5807         if (colormapped)
5808         {
5809                 if (!skinframe->qgeneratebase)
5810                         return;
5811         }
5812         else
5813         {
5814                 if (!skinframe->qgeneratemerged)
5815                         return;
5816         }
5817
5818         width = skinframe->qwidth;
5819         height = skinframe->qheight;
5820         skindata = skinframe->qpixels;
5821
5822         if (skinframe->qgeneratenmap)
5823         {
5824                 unsigned char *temp1, *temp2;
5825                 skinframe->qgeneratenmap = false;
5826                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5827                 temp2 = temp1 + width * height * 4;
5828                 // use either a custom palette or the quake palette
5829                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
5830                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5831                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5832                 Mem_Free(temp1);
5833         }
5834
5835         if (skinframe->qgenerateglow)
5836         {
5837                 skinframe->qgenerateglow = false;
5838                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
5839         }
5840
5841         if (colormapped)
5842         {
5843                 skinframe->qgeneratebase = false;
5844                 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);
5845                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
5846                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
5847         }
5848         else
5849         {
5850                 skinframe->qgeneratemerged = false;
5851                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
5852         }
5853
5854         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
5855         {
5856                 Mem_Free(skinframe->qpixels);
5857                 skinframe->qpixels = NULL;
5858         }
5859 }
5860
5861 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)
5862 {
5863         int i;
5864         skinframe_t *skinframe;
5865
5866         if (cls.state == ca_dedicated)
5867                 return NULL;
5868
5869         // if already loaded just return it, otherwise make a new skinframe
5870         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5871         if (skinframe && skinframe->base)
5872                 return skinframe;
5873
5874         skinframe->stain = NULL;
5875         skinframe->merged = NULL;
5876         skinframe->base = NULL;
5877         skinframe->pants = NULL;
5878         skinframe->shirt = NULL;
5879         skinframe->nmap = NULL;
5880         skinframe->gloss = NULL;
5881         skinframe->glow = NULL;
5882         skinframe->fog = NULL;
5883         skinframe->reflect = NULL;
5884         skinframe->hasalpha = false;
5885
5886         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5887         if (!skindata)
5888                 return NULL;
5889
5890         if (developer_loading.integer)
5891                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
5892
5893         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
5894         if (textureflags & TEXF_ALPHA)
5895         {
5896                 for (i = 0;i < width * height;i++)
5897                 {
5898                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
5899                         {
5900                                 skinframe->hasalpha = true;
5901                                 break;
5902                         }
5903                 }
5904                 if (r_loadfog && skinframe->hasalpha)
5905                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
5906         }
5907
5908         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
5909         //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]);
5910
5911         return skinframe;
5912 }
5913
5914 skinframe_t *R_SkinFrame_LoadMissing(void)
5915 {
5916         skinframe_t *skinframe;
5917
5918         if (cls.state == ca_dedicated)
5919                 return NULL;
5920
5921         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
5922         skinframe->stain = NULL;
5923         skinframe->merged = NULL;
5924         skinframe->base = NULL;
5925         skinframe->pants = NULL;
5926         skinframe->shirt = NULL;
5927         skinframe->nmap = NULL;
5928         skinframe->gloss = NULL;
5929         skinframe->glow = NULL;
5930         skinframe->fog = NULL;
5931         skinframe->reflect = NULL;
5932         skinframe->hasalpha = false;
5933
5934         skinframe->avgcolor[0] = rand() / RAND_MAX;
5935         skinframe->avgcolor[1] = rand() / RAND_MAX;
5936         skinframe->avgcolor[2] = rand() / RAND_MAX;
5937         skinframe->avgcolor[3] = 1;
5938
5939         return skinframe;
5940 }
5941
5942 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
5943 typedef struct suffixinfo_s
5944 {
5945         char *suffix;
5946         qboolean flipx, flipy, flipdiagonal;
5947 }
5948 suffixinfo_t;
5949 static suffixinfo_t suffix[3][6] =
5950 {
5951         {
5952                 {"px",   false, false, false},
5953                 {"nx",   false, false, false},
5954                 {"py",   false, false, false},
5955                 {"ny",   false, false, false},
5956                 {"pz",   false, false, false},
5957                 {"nz",   false, false, false}
5958         },
5959         {
5960                 {"posx", false, false, false},
5961                 {"negx", false, false, false},
5962                 {"posy", false, false, false},
5963                 {"negy", false, false, false},
5964                 {"posz", false, false, false},
5965                 {"negz", false, false, false}
5966         },
5967         {
5968                 {"rt",    true, false,  true},
5969                 {"lf",   false,  true,  true},
5970                 {"ft",    true,  true, false},
5971                 {"bk",   false, false, false},
5972                 {"up",    true, false,  true},
5973                 {"dn",    true, false,  true}
5974         }
5975 };
5976
5977 static int componentorder[4] = {0, 1, 2, 3};
5978
5979 rtexture_t *R_LoadCubemap(const char *basename)
5980 {
5981         int i, j, cubemapsize;
5982         unsigned char *cubemappixels, *image_buffer;
5983         rtexture_t *cubemaptexture;
5984         char name[256];
5985         // must start 0 so the first loadimagepixels has no requested width/height
5986         cubemapsize = 0;
5987         cubemappixels = NULL;
5988         cubemaptexture = NULL;
5989         // keep trying different suffix groups (posx, px, rt) until one loads
5990         for (j = 0;j < 3 && !cubemappixels;j++)
5991         {
5992                 // load the 6 images in the suffix group
5993                 for (i = 0;i < 6;i++)
5994                 {
5995                         // generate an image name based on the base and and suffix
5996                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
5997                         // load it
5998                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer)))
5999                         {
6000                                 // an image loaded, make sure width and height are equal
6001                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6002                                 {
6003                                         // if this is the first image to load successfully, allocate the cubemap memory
6004                                         if (!cubemappixels && image_width >= 1)
6005                                         {
6006                                                 cubemapsize = image_width;
6007                                                 // note this clears to black, so unavailable sides are black
6008                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6009                                         }
6010                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6011                                         if (cubemappixels)
6012                                                 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);
6013                                 }
6014                                 else
6015                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6016                                 // free the image
6017                                 Mem_Free(image_buffer);
6018                         }
6019                 }
6020         }
6021         // if a cubemap loaded, upload it
6022         if (cubemappixels)
6023         {
6024                 if (developer_loading.integer)
6025                         Con_Printf("loading cubemap \"%s\"\n", basename);
6026
6027                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR, NULL);
6028                 Mem_Free(cubemappixels);
6029         }
6030         else
6031         {
6032                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6033                 if (developer_loading.integer)
6034                 {
6035                         Con_Printf("(tried tried images ");
6036                         for (j = 0;j < 3;j++)
6037                                 for (i = 0;i < 6;i++)
6038                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
6039                         Con_Print(" and was unable to find any of them).\n");
6040                 }
6041         }
6042         return cubemaptexture;
6043 }
6044
6045 rtexture_t *R_GetCubemap(const char *basename)
6046 {
6047         int i;
6048         for (i = 0;i < r_texture_numcubemaps;i++)
6049                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6050                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6051         if (i >= MAX_CUBEMAPS)
6052                 return r_texture_whitecube;
6053         r_texture_numcubemaps++;
6054         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6055         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6056         return r_texture_cubemaps[i].texture;
6057 }
6058
6059 void R_FreeCubemaps(void)
6060 {
6061         int i;
6062         for (i = 0;i < r_texture_numcubemaps;i++)
6063         {
6064                 if (developer_loading.integer)
6065                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6066                 if (r_texture_cubemaps[i].texture)
6067                         R_FreeTexture(r_texture_cubemaps[i].texture);
6068         }
6069         r_texture_numcubemaps = 0;
6070 }
6071
6072 void R_Main_FreeViewCache(void)
6073 {
6074         if (r_refdef.viewcache.entityvisible)
6075                 Mem_Free(r_refdef.viewcache.entityvisible);
6076         if (r_refdef.viewcache.world_pvsbits)
6077                 Mem_Free(r_refdef.viewcache.world_pvsbits);
6078         if (r_refdef.viewcache.world_leafvisible)
6079                 Mem_Free(r_refdef.viewcache.world_leafvisible);
6080         if (r_refdef.viewcache.world_surfacevisible)
6081                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6082         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6083 }
6084
6085 void R_Main_ResizeViewCache(void)
6086 {
6087         int numentities = r_refdef.scene.numentities;
6088         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6089         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6090         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6091         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6092         if (r_refdef.viewcache.maxentities < numentities)
6093         {
6094                 r_refdef.viewcache.maxentities = numentities;
6095                 if (r_refdef.viewcache.entityvisible)
6096                         Mem_Free(r_refdef.viewcache.entityvisible);
6097                 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6098         }
6099         if (r_refdef.viewcache.world_numclusters != numclusters)
6100         {
6101                 r_refdef.viewcache.world_numclusters = numclusters;
6102                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6103                 if (r_refdef.viewcache.world_pvsbits)
6104                         Mem_Free(r_refdef.viewcache.world_pvsbits);
6105                 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6106         }
6107         if (r_refdef.viewcache.world_numleafs != numleafs)
6108         {
6109                 r_refdef.viewcache.world_numleafs = numleafs;
6110                 if (r_refdef.viewcache.world_leafvisible)
6111                         Mem_Free(r_refdef.viewcache.world_leafvisible);
6112                 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6113         }
6114         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6115         {
6116                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6117                 if (r_refdef.viewcache.world_surfacevisible)
6118                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
6119                 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6120         }
6121 }
6122
6123 extern rtexture_t *loadingscreentexture;
6124 void gl_main_start(void)
6125 {
6126         loadingscreentexture = NULL;
6127         r_texture_blanknormalmap = NULL;
6128         r_texture_white = NULL;
6129         r_texture_grey128 = NULL;
6130         r_texture_black = NULL;
6131         r_texture_whitecube = NULL;
6132         r_texture_normalizationcube = NULL;
6133         r_texture_fogattenuation = NULL;
6134         r_texture_gammaramps = NULL;
6135         r_texture_numcubemaps = 0;
6136
6137         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
6138         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6139
6140         switch(vid.renderpath)
6141         {
6142         case RENDERPATH_GL20:
6143         case RENDERPATH_CGGL:
6144                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6145                 Cvar_SetValueQuick(&gl_combine, 1);
6146                 Cvar_SetValueQuick(&r_glsl, 1);
6147                 r_loadnormalmap = true;
6148                 r_loadgloss = true;
6149                 r_loadfog = false;
6150                 break;
6151         case RENDERPATH_GL13:
6152                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6153                 Cvar_SetValueQuick(&gl_combine, 1);
6154                 Cvar_SetValueQuick(&r_glsl, 0);
6155                 r_loadnormalmap = false;
6156                 r_loadgloss = false;
6157                 r_loadfog = true;
6158                 break;
6159         case RENDERPATH_GL11:
6160                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6161                 Cvar_SetValueQuick(&gl_combine, 0);
6162                 Cvar_SetValueQuick(&r_glsl, 0);
6163                 r_loadnormalmap = false;
6164                 r_loadgloss = false;
6165                 r_loadfog = true;
6166                 break;
6167         }
6168
6169         R_AnimCache_Free();
6170         R_FrameData_Reset();
6171
6172         r_numqueries = 0;
6173         r_maxqueries = 0;
6174         memset(r_queries, 0, sizeof(r_queries));
6175
6176         r_qwskincache = NULL;
6177         r_qwskincache_size = 0;
6178
6179         // set up r_skinframe loading system for textures
6180         memset(&r_skinframe, 0, sizeof(r_skinframe));
6181         r_skinframe.loadsequence = 1;
6182         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
6183
6184         r_main_texturepool = R_AllocTexturePool();
6185         R_BuildBlankTextures();
6186         R_BuildNoTexture();
6187         if (vid.support.arb_texture_cube_map)
6188         {
6189                 R_BuildWhiteCube();
6190                 R_BuildNormalizationCube();
6191         }
6192         r_texture_fogattenuation = NULL;
6193         r_texture_gammaramps = NULL;
6194         //r_texture_fogintensity = NULL;
6195         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6196         memset(&r_waterstate, 0, sizeof(r_waterstate));
6197         r_glsl_permutation = NULL;
6198         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6199         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
6200         glslshaderstring = NULL;
6201 #ifdef SUPPORTCG
6202         r_cg_permutation = NULL;
6203         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
6204         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
6205         cgshaderstring = NULL;
6206 #endif
6207         memset(&r_svbsp, 0, sizeof (r_svbsp));
6208
6209         r_refdef.fogmasktable_density = 0;
6210 }
6211
6212 void gl_main_shutdown(void)
6213 {
6214         R_AnimCache_Free();
6215         R_FrameData_Reset();
6216
6217         R_Main_FreeViewCache();
6218
6219         if (r_maxqueries)
6220                 qglDeleteQueriesARB(r_maxqueries, r_queries);
6221
6222         r_numqueries = 0;
6223         r_maxqueries = 0;
6224         memset(r_queries, 0, sizeof(r_queries));
6225
6226         r_qwskincache = NULL;
6227         r_qwskincache_size = 0;
6228
6229         // clear out the r_skinframe state
6230         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
6231         memset(&r_skinframe, 0, sizeof(r_skinframe));
6232
6233         if (r_svbsp.nodes)
6234                 Mem_Free(r_svbsp.nodes);
6235         memset(&r_svbsp, 0, sizeof (r_svbsp));
6236         R_FreeTexturePool(&r_main_texturepool);
6237         loadingscreentexture = NULL;
6238         r_texture_blanknormalmap = NULL;
6239         r_texture_white = NULL;
6240         r_texture_grey128 = NULL;
6241         r_texture_black = NULL;
6242         r_texture_whitecube = NULL;
6243         r_texture_normalizationcube = NULL;
6244         r_texture_fogattenuation = NULL;
6245         r_texture_gammaramps = NULL;
6246         r_texture_numcubemaps = 0;
6247         //r_texture_fogintensity = NULL;
6248         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6249         memset(&r_waterstate, 0, sizeof(r_waterstate));
6250         r_glsl_permutation = NULL;
6251         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6252         glslshaderstring = NULL;
6253 #ifdef SUPPORTCG
6254         r_cg_permutation = NULL;
6255         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
6256         cgshaderstring = NULL;
6257 #endif
6258         R_GLSL_Restart_f();
6259 }
6260
6261 extern void CL_ParseEntityLump(char *entitystring);
6262 void gl_main_newmap(void)
6263 {
6264         // FIXME: move this code to client
6265         int l;
6266         char *entities, entname[MAX_QPATH];
6267         if (r_qwskincache)
6268                 Mem_Free(r_qwskincache);
6269         r_qwskincache = NULL;
6270         r_qwskincache_size = 0;
6271         if (cl.worldmodel)
6272         {
6273                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
6274                 l = (int)strlen(entname) - 4;
6275                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
6276                 {
6277                         memcpy(entname + l, ".ent", 5);
6278                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
6279                         {
6280                                 CL_ParseEntityLump(entities);
6281                                 Mem_Free(entities);
6282                                 return;
6283                         }
6284                 }
6285                 if (cl.worldmodel->brush.entities)
6286                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
6287         }
6288         R_Main_FreeViewCache();
6289
6290         R_FrameData_Reset();
6291 }
6292
6293 void GL_Main_Init(void)
6294 {
6295         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
6296
6297         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
6298         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
6299         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
6300         if (gamemode == GAME_NEHAHRA)
6301         {
6302                 Cvar_RegisterVariable (&gl_fogenable);
6303                 Cvar_RegisterVariable (&gl_fogdensity);
6304                 Cvar_RegisterVariable (&gl_fogred);
6305                 Cvar_RegisterVariable (&gl_foggreen);
6306                 Cvar_RegisterVariable (&gl_fogblue);
6307                 Cvar_RegisterVariable (&gl_fogstart);
6308                 Cvar_RegisterVariable (&gl_fogend);
6309                 Cvar_RegisterVariable (&gl_skyclip);
6310         }
6311         Cvar_RegisterVariable(&r_motionblur);
6312         Cvar_RegisterVariable(&r_motionblur_maxblur);
6313         Cvar_RegisterVariable(&r_motionblur_bmin);
6314         Cvar_RegisterVariable(&r_motionblur_vmin);
6315         Cvar_RegisterVariable(&r_motionblur_vmax);
6316         Cvar_RegisterVariable(&r_motionblur_vcoeff);
6317         Cvar_RegisterVariable(&r_motionblur_randomize);
6318         Cvar_RegisterVariable(&r_damageblur);
6319         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
6320         Cvar_RegisterVariable(&r_equalize_entities_minambient);
6321         Cvar_RegisterVariable(&r_equalize_entities_by);
6322         Cvar_RegisterVariable(&r_equalize_entities_to);
6323         Cvar_RegisterVariable(&r_depthfirst);
6324         Cvar_RegisterVariable(&r_useinfinitefarclip);
6325         Cvar_RegisterVariable(&r_farclip_base);
6326         Cvar_RegisterVariable(&r_farclip_world);
6327         Cvar_RegisterVariable(&r_nearclip);
6328         Cvar_RegisterVariable(&r_showbboxes);
6329         Cvar_RegisterVariable(&r_showsurfaces);
6330         Cvar_RegisterVariable(&r_showtris);
6331         Cvar_RegisterVariable(&r_shownormals);
6332         Cvar_RegisterVariable(&r_showlighting);
6333         Cvar_RegisterVariable(&r_showshadowvolumes);
6334         Cvar_RegisterVariable(&r_showcollisionbrushes);
6335         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
6336         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
6337         Cvar_RegisterVariable(&r_showdisabledepthtest);
6338         Cvar_RegisterVariable(&r_drawportals);
6339         Cvar_RegisterVariable(&r_drawentities);
6340         Cvar_RegisterVariable(&r_cullentities_trace);
6341         Cvar_RegisterVariable(&r_cullentities_trace_samples);
6342         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
6343         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
6344         Cvar_RegisterVariable(&r_cullentities_trace_delay);
6345         Cvar_RegisterVariable(&r_drawviewmodel);
6346         Cvar_RegisterVariable(&r_drawexteriormodel);
6347         Cvar_RegisterVariable(&r_speeds);
6348         Cvar_RegisterVariable(&r_fullbrights);
6349         Cvar_RegisterVariable(&r_wateralpha);
6350         Cvar_RegisterVariable(&r_dynamic);
6351         Cvar_RegisterVariable(&r_fullbright);
6352         Cvar_RegisterVariable(&r_shadows);
6353         Cvar_RegisterVariable(&r_shadows_darken);
6354         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
6355         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
6356         Cvar_RegisterVariable(&r_shadows_throwdistance);
6357         Cvar_RegisterVariable(&r_shadows_throwdirection);
6358         Cvar_RegisterVariable(&r_shadows_focus);
6359         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
6360         Cvar_RegisterVariable(&r_q1bsp_skymasking);
6361         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
6362         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
6363         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
6364         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
6365         Cvar_RegisterVariable(&r_fog_exp2);
6366         Cvar_RegisterVariable(&r_drawfog);
6367         Cvar_RegisterVariable(&r_transparentdepthmasking);
6368         Cvar_RegisterVariable(&r_texture_dds_load);
6369         Cvar_RegisterVariable(&r_texture_dds_save);
6370         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
6371         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
6372         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
6373         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
6374         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
6375         Cvar_RegisterVariable(&r_textureunits);
6376         Cvar_RegisterVariable(&gl_combine);
6377         Cvar_RegisterVariable(&r_glsl);
6378         Cvar_RegisterVariable(&r_glsl_deluxemapping);
6379         Cvar_RegisterVariable(&r_glsl_offsetmapping);
6380         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
6381         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
6382         Cvar_RegisterVariable(&r_glsl_postprocess);
6383         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
6384         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
6385         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
6386         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
6387         Cvar_RegisterVariable(&r_water);
6388         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
6389         Cvar_RegisterVariable(&r_water_clippingplanebias);
6390         Cvar_RegisterVariable(&r_water_refractdistort);
6391         Cvar_RegisterVariable(&r_water_reflectdistort);
6392         Cvar_RegisterVariable(&r_lerpsprites);
6393         Cvar_RegisterVariable(&r_lerpmodels);
6394         Cvar_RegisterVariable(&r_lerplightstyles);
6395         Cvar_RegisterVariable(&r_waterscroll);
6396         Cvar_RegisterVariable(&r_bloom);
6397         Cvar_RegisterVariable(&r_bloom_colorscale);
6398         Cvar_RegisterVariable(&r_bloom_brighten);
6399         Cvar_RegisterVariable(&r_bloom_blur);
6400         Cvar_RegisterVariable(&r_bloom_resolution);
6401         Cvar_RegisterVariable(&r_bloom_colorexponent);
6402         Cvar_RegisterVariable(&r_bloom_colorsubtract);
6403         Cvar_RegisterVariable(&r_hdr);
6404         Cvar_RegisterVariable(&r_hdr_scenebrightness);
6405         Cvar_RegisterVariable(&r_hdr_glowintensity);
6406         Cvar_RegisterVariable(&r_hdr_range);
6407         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
6408         Cvar_RegisterVariable(&developer_texturelogging);
6409         Cvar_RegisterVariable(&gl_lightmaps);
6410         Cvar_RegisterVariable(&r_test);
6411         Cvar_RegisterVariable(&r_batchmode);
6412         Cvar_RegisterVariable(&r_glsl_saturation);
6413         Cvar_RegisterVariable(&r_framedatasize);
6414         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
6415                 Cvar_SetValue("r_fullbrights", 0);
6416         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
6417
6418         Cvar_RegisterVariable(&r_track_sprites);
6419         Cvar_RegisterVariable(&r_track_sprites_flags);
6420         Cvar_RegisterVariable(&r_track_sprites_scalew);
6421         Cvar_RegisterVariable(&r_track_sprites_scaleh);
6422         Cvar_RegisterVariable(&r_overheadsprites_perspective);
6423         Cvar_RegisterVariable(&r_overheadsprites_pushback);
6424 }
6425
6426 extern void R_Textures_Init(void);
6427 extern void GL_Draw_Init(void);
6428 extern void GL_Main_Init(void);
6429 extern void R_Shadow_Init(void);
6430 extern void R_Sky_Init(void);
6431 extern void GL_Surf_Init(void);
6432 extern void R_Particles_Init(void);
6433 extern void R_Explosion_Init(void);
6434 extern void gl_backend_init(void);
6435 extern void Sbar_Init(void);
6436 extern void R_LightningBeams_Init(void);
6437 extern void Mod_RenderInit(void);
6438 extern void Font_Init(void);
6439
6440 void Render_Init(void)
6441 {
6442         gl_backend_init();
6443         R_Textures_Init();
6444         GL_Main_Init();
6445         Font_Init();
6446         GL_Draw_Init();
6447         R_Shadow_Init();
6448         R_Sky_Init();
6449         GL_Surf_Init();
6450         Sbar_Init();
6451         R_Particles_Init();
6452         R_Explosion_Init();
6453         R_LightningBeams_Init();
6454         Mod_RenderInit();
6455 }
6456
6457 /*
6458 ===============
6459 GL_Init
6460 ===============
6461 */
6462 extern char *ENGINE_EXTENSIONS;
6463 void GL_Init (void)
6464 {
6465         gl_renderer = (const char *)qglGetString(GL_RENDERER);
6466         gl_vendor = (const char *)qglGetString(GL_VENDOR);
6467         gl_version = (const char *)qglGetString(GL_VERSION);
6468         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
6469
6470         if (!gl_extensions)
6471                 gl_extensions = "";
6472         if (!gl_platformextensions)
6473                 gl_platformextensions = "";
6474
6475         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
6476         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
6477         Con_Printf("GL_VERSION: %s\n", gl_version);
6478         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
6479         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
6480
6481         VID_CheckExtensions();
6482
6483         // LordHavoc: report supported extensions
6484         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
6485
6486         // clear to black (loading plaque will be seen over this)
6487         CHECKGLERROR
6488         qglClearColor(0,0,0,1);CHECKGLERROR
6489         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
6490 }
6491
6492 int R_CullBox(const vec3_t mins, const vec3_t maxs)
6493 {
6494         int i;
6495         mplane_t *p;
6496         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6497         {
6498                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
6499                 if (i == 4)
6500                         continue;
6501                 p = r_refdef.view.frustum + i;
6502                 switch(p->signbits)
6503                 {
6504                 default:
6505                 case 0:
6506                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6507                                 return true;
6508                         break;
6509                 case 1:
6510                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6511                                 return true;
6512                         break;
6513                 case 2:
6514                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6515                                 return true;
6516                         break;
6517                 case 3:
6518                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6519                                 return true;
6520                         break;
6521                 case 4:
6522                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6523                                 return true;
6524                         break;
6525                 case 5:
6526                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6527                                 return true;
6528                         break;
6529                 case 6:
6530                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6531                                 return true;
6532                         break;
6533                 case 7:
6534                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6535                                 return true;
6536                         break;
6537                 }
6538         }
6539         return false;
6540 }
6541
6542 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
6543 {
6544         int i;
6545         const mplane_t *p;
6546         for (i = 0;i < numplanes;i++)
6547         {
6548                 p = planes + i;
6549                 switch(p->signbits)
6550                 {
6551                 default:
6552                 case 0:
6553                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6554                                 return true;
6555                         break;
6556                 case 1:
6557                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6558                                 return true;
6559                         break;
6560                 case 2:
6561                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6562                                 return true;
6563                         break;
6564                 case 3:
6565                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6566                                 return true;
6567                         break;
6568                 case 4:
6569                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6570                                 return true;
6571                         break;
6572                 case 5:
6573                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6574                                 return true;
6575                         break;
6576                 case 6:
6577                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6578                                 return true;
6579                         break;
6580                 case 7:
6581                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6582                                 return true;
6583                         break;
6584                 }
6585         }
6586         return false;
6587 }
6588
6589 //==================================================================================
6590
6591 // LordHavoc: this stores temporary data used within the same frame
6592
6593 qboolean r_framedata_failed;
6594 static size_t r_framedata_size;
6595 static size_t r_framedata_current;
6596 static void *r_framedata_base;
6597
6598 void R_FrameData_Reset(void)
6599 {
6600         if (r_framedata_base)
6601                 Mem_Free(r_framedata_base);
6602         r_framedata_base = NULL;
6603         r_framedata_size = 0;
6604         r_framedata_current = 0;
6605         r_framedata_failed = false;
6606 }
6607
6608 void R_FrameData_NewFrame(void)
6609 {
6610         size_t wantedsize;
6611         if (r_framedata_failed)
6612                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
6613         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
6614         wantedsize = bound(65536, wantedsize, 128*1024*1024);
6615         if (r_framedata_size != wantedsize)
6616         {
6617                 r_framedata_size = wantedsize;
6618                 if (r_framedata_base)
6619                         Mem_Free(r_framedata_base);
6620                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
6621         }
6622         r_framedata_current = 0;
6623         r_framedata_failed = false;
6624 }
6625
6626 void *R_FrameData_Alloc(size_t size)
6627 {
6628         void *data;
6629
6630         // align to 16 byte boundary
6631         size = (size + 15) & ~15;
6632         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
6633         r_framedata_current += size;
6634
6635         // check overflow
6636         if (r_framedata_current > r_framedata_size)
6637                 r_framedata_failed = true;
6638
6639         // return NULL on everything after a failure
6640         if (r_framedata_failed)
6641                 return NULL;
6642
6643         return data;
6644 }
6645
6646 void *R_FrameData_Store(size_t size, void *data)
6647 {
6648         void *d = R_FrameData_Alloc(size);
6649         if (d)
6650                 memcpy(d, data, size);
6651         return d;
6652 }
6653
6654 //==================================================================================
6655
6656 // LordHavoc: animcache originally written by Echon, rewritten since then
6657
6658 /**
6659  * Animation cache prevents re-generating mesh data for an animated model
6660  * multiple times in one frame for lighting, shadowing, reflections, etc.
6661  */
6662
6663 void R_AnimCache_Free(void)
6664 {
6665 }
6666
6667 void R_AnimCache_ClearCache(void)
6668 {
6669         int i;
6670         entity_render_t *ent;
6671
6672         for (i = 0;i < r_refdef.scene.numentities;i++)
6673         {
6674                 ent = r_refdef.scene.entities[i];
6675                 ent->animcache_vertex3f = NULL;
6676                 ent->animcache_normal3f = NULL;
6677                 ent->animcache_svector3f = NULL;
6678                 ent->animcache_tvector3f = NULL;
6679         }
6680 }
6681
6682 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6683 {
6684         dp_model_t *model = ent->model;
6685         int numvertices;
6686         // see if it's already cached this frame
6687         if (ent->animcache_vertex3f)
6688         {
6689                 // add normals/tangents if needed
6690                 if (wantnormals || wanttangents)
6691                 {
6692                         if (ent->animcache_normal3f)
6693                                 wantnormals = false;
6694                         if (ent->animcache_svector3f)
6695                                 wanttangents = false;
6696                         if (wantnormals || wanttangents)
6697                         {
6698                                 numvertices = model->surfmesh.num_vertices;
6699                                 if (wantnormals)
6700                                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6701                                 if (wanttangents)
6702                                 {
6703                                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6704                                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6705                                 }
6706                                 if (!r_framedata_failed)
6707                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
6708                         }
6709                 }
6710         }
6711         else
6712         {
6713                 // see if this ent is worth caching
6714                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
6715                         return false;
6716                 // get some memory for this entity and generate mesh data
6717                 numvertices = model->surfmesh.num_vertices;
6718                 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6719                 if (wantnormals)
6720                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6721                 if (wanttangents)
6722                 {
6723                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6724                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6725                 }
6726                 if (!r_framedata_failed)
6727                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
6728         }
6729         return !r_framedata_failed;
6730 }
6731
6732 void R_AnimCache_CacheVisibleEntities(void)
6733 {
6734         int i;
6735         qboolean wantnormals = !r_showsurfaces.integer;
6736         qboolean wanttangents = !r_showsurfaces.integer;
6737
6738         switch(vid.renderpath)
6739         {
6740         case RENDERPATH_GL20:
6741         case RENDERPATH_CGGL:
6742                 break;
6743         case RENDERPATH_GL13:
6744         case RENDERPATH_GL11:
6745                 wanttangents = false;
6746                 break;
6747         }
6748
6749         // TODO: thread this
6750         // NOTE: R_PrepareRTLights() also caches entities
6751
6752         for (i = 0;i < r_refdef.scene.numentities;i++)
6753                 if (r_refdef.viewcache.entityvisible[i])
6754                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
6755 }
6756
6757 //==================================================================================
6758
6759 static void R_View_UpdateEntityLighting (void)
6760 {
6761         int i;
6762         entity_render_t *ent;
6763         vec3_t tempdiffusenormal, avg;
6764         vec_t f, fa, fd, fdd;
6765         qboolean skipunseen = r_shadows.integer != 1 || R_Shadow_ShadowMappingEnabled();
6766
6767         for (i = 0;i < r_refdef.scene.numentities;i++)
6768         {
6769                 ent = r_refdef.scene.entities[i];
6770
6771                 // skip unseen models
6772                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
6773                         continue;
6774
6775                 // skip bsp models
6776                 if (ent->model && ent->model->brush.num_leafs)
6777                 {
6778                         // TODO: use modellight for r_ambient settings on world?
6779                         VectorSet(ent->modellight_ambient, 0, 0, 0);
6780                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
6781                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
6782                         continue;
6783                 }
6784
6785                 // fetch the lighting from the worldmodel data
6786                 VectorClear(ent->modellight_ambient);
6787                 VectorClear(ent->modellight_diffuse);
6788                 VectorClear(tempdiffusenormal);
6789                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
6790                 {
6791                         vec3_t org;
6792                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6793                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
6794                         if(ent->flags & RENDER_EQUALIZE)
6795                         {
6796                                 // first fix up ambient lighting...
6797                                 if(r_equalize_entities_minambient.value > 0)
6798                                 {
6799                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
6800                                         if(fd > 0)
6801                                         {
6802                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
6803                                                 if(fa < r_equalize_entities_minambient.value * fd)
6804                                                 {
6805                                                         // solve:
6806                                                         //   fa'/fd' = minambient
6807                                                         //   fa'+0.25*fd' = fa+0.25*fd
6808                                                         //   ...
6809                                                         //   fa' = fd' * minambient
6810                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
6811                                                         //   ...
6812                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
6813                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
6814                                                         //   ...
6815                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
6816                                                         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
6817                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
6818                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6819                                                 }
6820                                         }
6821                                 }
6822
6823                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
6824                                 {
6825                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
6826                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
6827                                         if(f > 0)
6828                                         {
6829                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
6830                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
6831                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6832                                         }
6833                                 }
6834                         }
6835                 }
6836                 else // highly rare
6837                         VectorSet(ent->modellight_ambient, 1, 1, 1);
6838
6839                 // move the light direction into modelspace coordinates for lighting code
6840                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
6841                 if(VectorLength2(ent->modellight_lightdir) == 0)
6842                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
6843                 VectorNormalize(ent->modellight_lightdir);
6844         }
6845 }
6846
6847 #define MAX_LINEOFSIGHTTRACES 64
6848
6849 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
6850 {
6851         int i;
6852         vec3_t boxmins, boxmaxs;
6853         vec3_t start;
6854         vec3_t end;
6855         dp_model_t *model = r_refdef.scene.worldmodel;
6856
6857         if (!model || !model->brush.TraceLineOfSight)
6858                 return true;
6859
6860         // expand the box a little
6861         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
6862         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
6863         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
6864         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
6865         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
6866         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
6867
6868         // return true if eye is inside enlarged box
6869         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
6870                 return true;
6871
6872         // try center
6873         VectorCopy(eye, start);
6874         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
6875         if (model->brush.TraceLineOfSight(model, start, end))
6876                 return true;
6877
6878         // try various random positions
6879         for (i = 0;i < numsamples;i++)
6880         {
6881                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
6882                 if (model->brush.TraceLineOfSight(model, start, end))
6883                         return true;
6884         }
6885
6886         return false;
6887 }
6888
6889
6890 static void R_View_UpdateEntityVisible (void)
6891 {
6892         int i;
6893         int renderimask;
6894         int samples;
6895         entity_render_t *ent;
6896
6897         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
6898                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
6899                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
6900                 :                                                          RENDER_EXTERIORMODEL;
6901         if (!r_drawviewmodel.integer)
6902                 renderimask |= RENDER_VIEWMODEL;
6903         if (!r_drawexteriormodel.integer)
6904                 renderimask |= RENDER_EXTERIORMODEL;
6905         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
6906         {
6907                 // worldmodel can check visibility
6908                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
6909                 for (i = 0;i < r_refdef.scene.numentities;i++)
6910                 {
6911                         ent = r_refdef.scene.entities[i];
6912                         if (!(ent->flags & renderimask))
6913                         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)))
6914                         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))
6915                                 r_refdef.viewcache.entityvisible[i] = true;
6916                 }
6917                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
6918                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
6919                 {
6920                         for (i = 0;i < r_refdef.scene.numentities;i++)
6921                         {
6922                                 ent = r_refdef.scene.entities[i];
6923                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
6924                                 {
6925                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
6926                                         if (samples < 0)
6927                                                 continue; // temp entities do pvs only
6928                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
6929                                                 ent->last_trace_visibility = realtime;
6930                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
6931                                                 r_refdef.viewcache.entityvisible[i] = 0;
6932                                 }
6933                         }
6934                 }
6935         }
6936         else
6937         {
6938                 // no worldmodel or it can't check visibility
6939                 for (i = 0;i < r_refdef.scene.numentities;i++)
6940                 {
6941                         ent = r_refdef.scene.entities[i];
6942                         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));
6943                 }
6944         }
6945 }
6946
6947 /// only used if skyrendermasked, and normally returns false
6948 int R_DrawBrushModelsSky (void)
6949 {
6950         int i, sky;
6951         entity_render_t *ent;
6952
6953         sky = false;
6954         for (i = 0;i < r_refdef.scene.numentities;i++)
6955         {
6956                 if (!r_refdef.viewcache.entityvisible[i])
6957                         continue;
6958                 ent = r_refdef.scene.entities[i];
6959                 if (!ent->model || !ent->model->DrawSky)
6960                         continue;
6961                 ent->model->DrawSky(ent);
6962                 sky = true;
6963         }
6964         return sky;
6965 }
6966
6967 static void R_DrawNoModel(entity_render_t *ent);
6968 static void R_DrawModels(void)
6969 {
6970         int i;
6971         entity_render_t *ent;
6972
6973         for (i = 0;i < r_refdef.scene.numentities;i++)
6974         {
6975                 if (!r_refdef.viewcache.entityvisible[i])
6976                         continue;
6977                 ent = r_refdef.scene.entities[i];
6978                 r_refdef.stats.entities++;
6979                 if (ent->model && ent->model->Draw != NULL)
6980                         ent->model->Draw(ent);
6981                 else
6982                         R_DrawNoModel(ent);
6983         }
6984 }
6985
6986 static void R_DrawModelsDepth(void)
6987 {
6988         int i;
6989         entity_render_t *ent;
6990
6991         for (i = 0;i < r_refdef.scene.numentities;i++)
6992         {
6993                 if (!r_refdef.viewcache.entityvisible[i])
6994                         continue;
6995                 ent = r_refdef.scene.entities[i];
6996                 if (ent->model && ent->model->DrawDepth != NULL)
6997                         ent->model->DrawDepth(ent);
6998         }
6999 }
7000
7001 static void R_DrawModelsDebug(void)
7002 {
7003         int i;
7004         entity_render_t *ent;
7005
7006         for (i = 0;i < r_refdef.scene.numentities;i++)
7007         {
7008                 if (!r_refdef.viewcache.entityvisible[i])
7009                         continue;
7010                 ent = r_refdef.scene.entities[i];
7011                 if (ent->model && ent->model->DrawDebug != NULL)
7012                         ent->model->DrawDebug(ent);
7013         }
7014 }
7015
7016 static void R_DrawModelsAddWaterPlanes(void)
7017 {
7018         int i;
7019         entity_render_t *ent;
7020
7021         for (i = 0;i < r_refdef.scene.numentities;i++)
7022         {
7023                 if (!r_refdef.viewcache.entityvisible[i])
7024                         continue;
7025                 ent = r_refdef.scene.entities[i];
7026                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
7027                         ent->model->DrawAddWaterPlanes(ent);
7028         }
7029 }
7030
7031 static void R_View_SetFrustum(void)
7032 {
7033         int i;
7034         double slopex, slopey;
7035         vec3_t forward, left, up, origin;
7036
7037         // we can't trust r_refdef.view.forward and friends in reflected scenes
7038         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
7039
7040 #if 0
7041         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
7042         r_refdef.view.frustum[0].normal[1] = 0 - 0;
7043         r_refdef.view.frustum[0].normal[2] = -1 - 0;
7044         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
7045         r_refdef.view.frustum[1].normal[1] = 0 + 0;
7046         r_refdef.view.frustum[1].normal[2] = -1 + 0;
7047         r_refdef.view.frustum[2].normal[0] = 0 - 0;
7048         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
7049         r_refdef.view.frustum[2].normal[2] = -1 - 0;
7050         r_refdef.view.frustum[3].normal[0] = 0 + 0;
7051         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
7052         r_refdef.view.frustum[3].normal[2] = -1 + 0;
7053 #endif
7054
7055 #if 0
7056         zNear = r_refdef.nearclip;
7057         nudge = 1.0 - 1.0 / (1<<23);
7058         r_refdef.view.frustum[4].normal[0] = 0 - 0;
7059         r_refdef.view.frustum[4].normal[1] = 0 - 0;
7060         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
7061         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
7062         r_refdef.view.frustum[5].normal[0] = 0 + 0;
7063         r_refdef.view.frustum[5].normal[1] = 0 + 0;
7064         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
7065         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
7066 #endif
7067
7068
7069
7070 #if 0
7071         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
7072         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
7073         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
7074         r_refdef.view.frustum[0].dist = m[15] - m[12];
7075
7076         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
7077         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
7078         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
7079         r_refdef.view.frustum[1].dist = m[15] + m[12];
7080
7081         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
7082         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
7083         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
7084         r_refdef.view.frustum[2].dist = m[15] - m[13];
7085
7086         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
7087         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
7088         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
7089         r_refdef.view.frustum[3].dist = m[15] + m[13];
7090
7091         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
7092         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
7093         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
7094         r_refdef.view.frustum[4].dist = m[15] - m[14];
7095
7096         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
7097         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
7098         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
7099         r_refdef.view.frustum[5].dist = m[15] + m[14];
7100 #endif
7101
7102         if (r_refdef.view.useperspective)
7103         {
7104                 slopex = 1.0 / r_refdef.view.frustum_x;
7105                 slopey = 1.0 / r_refdef.view.frustum_y;
7106                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
7107                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
7108                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
7109                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
7110                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7111
7112                 // Leaving those out was a mistake, those were in the old code, and they
7113                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
7114                 // I couldn't reproduce it after adding those normalizations. --blub
7115                 VectorNormalize(r_refdef.view.frustum[0].normal);
7116                 VectorNormalize(r_refdef.view.frustum[1].normal);
7117                 VectorNormalize(r_refdef.view.frustum[2].normal);
7118                 VectorNormalize(r_refdef.view.frustum[3].normal);
7119
7120                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
7121                 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]);
7122                 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]);
7123                 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]);
7124                 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]);
7125
7126                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
7127                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
7128                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
7129                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
7130                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7131         }
7132         else
7133         {
7134                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
7135                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
7136                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
7137                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
7138                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7139                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
7140                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
7141                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
7142                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
7143                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7144         }
7145         r_refdef.view.numfrustumplanes = 5;
7146
7147         if (r_refdef.view.useclipplane)
7148         {
7149                 r_refdef.view.numfrustumplanes = 6;
7150                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
7151         }
7152
7153         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7154                 PlaneClassify(r_refdef.view.frustum + i);
7155
7156         // LordHavoc: note to all quake engine coders, Quake had a special case
7157         // for 90 degrees which assumed a square view (wrong), so I removed it,
7158         // Quake2 has it disabled as well.
7159
7160         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
7161         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
7162         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
7163         //PlaneClassify(&frustum[0]);
7164
7165         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
7166         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
7167         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
7168         //PlaneClassify(&frustum[1]);
7169
7170         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
7171         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
7172         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
7173         //PlaneClassify(&frustum[2]);
7174
7175         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
7176         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
7177         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
7178         //PlaneClassify(&frustum[3]);
7179
7180         // nearclip plane
7181         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
7182         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
7183         //PlaneClassify(&frustum[4]);
7184 }
7185
7186 void R_View_Update(void)
7187 {
7188         R_Main_ResizeViewCache();
7189         R_View_SetFrustum();
7190         R_View_WorldVisibility(r_refdef.view.useclipplane);
7191         R_View_UpdateEntityVisible();
7192         R_View_UpdateEntityLighting();
7193 }
7194
7195 void R_SetupView(qboolean allowwaterclippingplane)
7196 {
7197         const float *customclipplane = NULL;
7198         float plane[4];
7199         if (r_refdef.view.useclipplane && allowwaterclippingplane)
7200         {
7201                 // LordHavoc: couldn't figure out how to make this approach the
7202                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
7203                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
7204                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
7205                         dist = r_refdef.view.clipplane.dist;
7206                 plane[0] = r_refdef.view.clipplane.normal[0];
7207                 plane[1] = r_refdef.view.clipplane.normal[1];
7208                 plane[2] = r_refdef.view.clipplane.normal[2];
7209                 plane[3] = dist;
7210                 customclipplane = plane;
7211         }
7212
7213         if (!r_refdef.view.useperspective)
7214                 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);
7215         else if (vid.stencil && r_useinfinitefarclip.integer)
7216                 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);
7217         else
7218                 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);
7219         R_SetViewport(&r_refdef.view.viewport);
7220 }
7221
7222 void R_EntityMatrix(const matrix4x4_t *matrix)
7223 {
7224         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
7225         {
7226                 gl_modelmatrixchanged = false;
7227                 gl_modelmatrix = *matrix;
7228                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
7229                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
7230                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
7231                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
7232                 CHECKGLERROR
7233                 switch(vid.renderpath)
7234                 {
7235                 case RENDERPATH_GL20:
7236                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
7237                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
7238                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7239                         break;
7240                 case RENDERPATH_CGGL:
7241 #ifdef SUPPORTCG
7242                         CHECKCGERROR
7243                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
7244                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
7245                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7246 #endif
7247                         break;
7248                 case RENDERPATH_GL13:
7249                 case RENDERPATH_GL11:
7250                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7251                         break;
7252                 }
7253         }
7254 }
7255
7256 void R_ResetViewRendering2D(void)
7257 {
7258         r_viewport_t viewport;
7259         DrawQ_Finish();
7260
7261         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
7262         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);
7263         R_SetViewport(&viewport);
7264         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
7265         GL_Color(1, 1, 1, 1);
7266         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7267         GL_BlendFunc(GL_ONE, GL_ZERO);
7268         GL_AlphaTest(false);
7269         GL_ScissorTest(false);
7270         GL_DepthMask(false);
7271         GL_DepthRange(0, 1);
7272         GL_DepthTest(false);
7273         R_EntityMatrix(&identitymatrix);
7274         R_Mesh_ResetTextureState();
7275         GL_PolygonOffset(0, 0);
7276         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7277         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7278         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7279         qglStencilMask(~0);CHECKGLERROR
7280         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7281         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7282         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
7283 }
7284
7285 void R_ResetViewRendering3D(void)
7286 {
7287         DrawQ_Finish();
7288
7289         R_SetupView(true);
7290         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7291         GL_Color(1, 1, 1, 1);
7292         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7293         GL_BlendFunc(GL_ONE, GL_ZERO);
7294         GL_AlphaTest(false);
7295         GL_ScissorTest(true);
7296         GL_DepthMask(true);
7297         GL_DepthRange(0, 1);
7298         GL_DepthTest(true);
7299         R_EntityMatrix(&identitymatrix);
7300         R_Mesh_ResetTextureState();
7301         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7302         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7303         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7304         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7305         qglStencilMask(~0);CHECKGLERROR
7306         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7307         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7308         GL_CullFace(r_refdef.view.cullface_back);
7309 }
7310
7311 /*
7312 ================
7313 R_RenderView_UpdateViewVectors
7314 ================
7315 */
7316 static void R_RenderView_UpdateViewVectors(void)
7317 {
7318         // break apart the view matrix into vectors for various purposes
7319         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
7320         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
7321         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
7322         VectorNegate(r_refdef.view.left, r_refdef.view.right);
7323         // make an inverted copy of the view matrix for tracking sprites
7324         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
7325 }
7326
7327 void R_RenderScene(void);
7328 void R_RenderWaterPlanes(void);
7329
7330 static void R_Water_StartFrame(void)
7331 {
7332         int i;
7333         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
7334         r_waterstate_waterplane_t *p;
7335
7336         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
7337                 return;
7338
7339         switch(vid.renderpath)
7340         {
7341         case RENDERPATH_GL20:
7342         case RENDERPATH_CGGL:
7343                 break;
7344         case RENDERPATH_GL13:
7345         case RENDERPATH_GL11:
7346                 return;
7347         }
7348
7349         // set waterwidth and waterheight to the water resolution that will be
7350         // used (often less than the screen resolution for faster rendering)
7351         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
7352         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
7353
7354         // calculate desired texture sizes
7355         // can't use water if the card does not support the texture size
7356         if (!r_water.integer || r_showsurfaces.integer)
7357                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
7358         else if (vid.support.arb_texture_non_power_of_two)
7359         {
7360                 texturewidth = waterwidth;
7361                 textureheight = waterheight;
7362                 camerawidth = waterwidth;
7363                 cameraheight = waterheight;
7364         }
7365         else
7366         {
7367                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
7368                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
7369                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
7370                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
7371         }
7372
7373         // allocate textures as needed
7374         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
7375         {
7376                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7377                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
7378                 {
7379                         if (p->texture_refraction)
7380                                 R_FreeTexture(p->texture_refraction);
7381                         p->texture_refraction = NULL;
7382                         if (p->texture_reflection)
7383                                 R_FreeTexture(p->texture_reflection);
7384                         p->texture_reflection = NULL;
7385                         if (p->texture_camera)
7386                                 R_FreeTexture(p->texture_camera);
7387                         p->texture_camera = NULL;
7388                 }
7389                 memset(&r_waterstate, 0, sizeof(r_waterstate));
7390                 r_waterstate.texturewidth = texturewidth;
7391                 r_waterstate.textureheight = textureheight;
7392                 r_waterstate.camerawidth = camerawidth;
7393                 r_waterstate.cameraheight = cameraheight;
7394         }
7395
7396         if (r_waterstate.texturewidth)
7397         {
7398                 r_waterstate.enabled = true;
7399
7400                 // when doing a reduced render (HDR) we want to use a smaller area
7401                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
7402                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
7403
7404                 // set up variables that will be used in shader setup
7405                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7406                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7407                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7408                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7409         }
7410
7411         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7412         r_waterstate.numwaterplanes = 0;
7413 }
7414
7415 void R_Water_AddWaterPlane(msurface_t *surface)
7416 {
7417         int triangleindex, planeindex;
7418         const int *e;
7419         vec3_t vert[3];
7420         vec3_t normal;
7421         vec3_t center;
7422         mplane_t plane;
7423         int cam_ent;
7424         r_waterstate_waterplane_t *p;
7425         texture_t *t = R_GetCurrentTexture(surface->texture);
7426         cam_ent = t->camera_entity;
7427         if(!(t->currentmaterialflags & MATERIALFLAG_CAMERA))
7428                 cam_ent = 0;
7429
7430         // just use the first triangle with a valid normal for any decisions
7431         VectorClear(normal);
7432         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
7433         {
7434                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
7435                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
7436                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
7437                 TriangleNormal(vert[0], vert[1], vert[2], normal);
7438                 if (VectorLength2(normal) >= 0.001)
7439                         break;
7440         }
7441
7442         VectorCopy(normal, plane.normal);
7443         VectorNormalize(plane.normal);
7444         plane.dist = DotProduct(vert[0], plane.normal);
7445         PlaneClassify(&plane);
7446         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
7447         {
7448                 // skip backfaces (except if nocullface is set)
7449                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
7450                         return;
7451                 VectorNegate(plane.normal, plane.normal);
7452                 plane.dist *= -1;
7453                 PlaneClassify(&plane);
7454         }
7455
7456
7457         // find a matching plane if there is one
7458         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7459                 if(p->camera_entity == t->camera_entity)
7460                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
7461                                 break;
7462         if (planeindex >= r_waterstate.maxwaterplanes)
7463                 return; // nothing we can do, out of planes
7464
7465         // if this triangle does not fit any known plane rendered this frame, add one
7466         if (planeindex >= r_waterstate.numwaterplanes)
7467         {
7468                 // store the new plane
7469                 r_waterstate.numwaterplanes++;
7470                 p->plane = plane;
7471                 // clear materialflags and pvs
7472                 p->materialflags = 0;
7473                 p->pvsvalid = false;
7474                 p->camera_entity = t->camera_entity;
7475         }
7476         // merge this surface's materialflags into the waterplane
7477         p->materialflags |= t->currentmaterialflags;
7478         if(!(p->materialflags & MATERIALFLAG_CAMERA))
7479         {
7480                 // merge this surface's PVS into the waterplane
7481                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
7482                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
7483                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
7484                 {
7485                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
7486                         p->pvsvalid = true;
7487                 }
7488         }
7489 }
7490
7491 static void R_Water_ProcessPlanes(void)
7492 {
7493         r_refdef_view_t originalview;
7494         r_refdef_view_t myview;
7495         int planeindex;
7496         r_waterstate_waterplane_t *p;
7497         vec3_t visorigin;
7498
7499         originalview = r_refdef.view;
7500
7501         // make sure enough textures are allocated
7502         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7503         {
7504                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7505                 {
7506                         if (!p->texture_refraction)
7507                                 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);
7508                         if (!p->texture_refraction)
7509                                 goto error;
7510                 }
7511                 else if (p->materialflags & MATERIALFLAG_CAMERA)
7512                 {
7513                         if (!p->texture_camera)
7514                                 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_waterstate.camerawidth, r_waterstate.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR, NULL);
7515                         if (!p->texture_camera)
7516                                 goto error;
7517                 }
7518
7519                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7520                 {
7521                         if (!p->texture_reflection)
7522                                 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);
7523                         if (!p->texture_reflection)
7524                                 goto error;
7525                 }
7526         }
7527
7528         // render views
7529         r_refdef.view = originalview;
7530         r_refdef.view.showdebug = false;
7531         r_refdef.view.width = r_waterstate.waterwidth;
7532         r_refdef.view.height = r_waterstate.waterheight;
7533         r_refdef.view.useclipplane = true;
7534         myview = r_refdef.view;
7535         r_waterstate.renderingscene = true;
7536         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7537         {
7538                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7539                 {
7540                         r_refdef.view = myview;
7541                         // render reflected scene and copy into texture
7542                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
7543                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
7544                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
7545                         r_refdef.view.clipplane = p->plane;
7546                         // reverse the cullface settings for this render
7547                         r_refdef.view.cullface_front = GL_FRONT;
7548                         r_refdef.view.cullface_back = GL_BACK;
7549                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
7550                         {
7551                                 r_refdef.view.usecustompvs = true;
7552                                 if (p->pvsvalid)
7553                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7554                                 else
7555                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7556                         }
7557
7558                         R_ResetViewRendering3D();
7559                         R_ClearScreen(r_refdef.fogenabled);
7560                         R_View_Update();
7561                         R_RenderScene();
7562
7563                         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);
7564                 }
7565
7566                 // render the normal view scene and copy into texture
7567                 // (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)
7568                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7569                 {
7570                         r_waterstate.renderingrefraction = true;
7571                         r_refdef.view = myview;
7572
7573                         r_refdef.view.clipplane = p->plane;
7574                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
7575                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
7576
7577                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
7578                         {
7579                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
7580                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
7581                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
7582                                 R_RenderView_UpdateViewVectors();
7583                                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
7584                         }
7585
7586                         PlaneClassify(&r_refdef.view.clipplane);
7587
7588                         R_ResetViewRendering3D();
7589                         R_ClearScreen(r_refdef.fogenabled);
7590                         R_View_Update();
7591                         R_RenderScene();
7592
7593                         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);
7594                         r_waterstate.renderingrefraction = false;
7595                 }
7596                 else if (p->materialflags & MATERIALFLAG_CAMERA)
7597                 {
7598                         r_refdef.view = myview;
7599
7600                         r_refdef.view.clipplane = p->plane;
7601                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
7602                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
7603
7604                         r_refdef.view.width = r_waterstate.camerawidth;
7605                         r_refdef.view.height = r_waterstate.cameraheight;
7606                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
7607                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
7608
7609                         if(p->camera_entity)
7610                         {
7611                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
7612                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
7613                         }
7614
7615                         // reverse the cullface settings for this render
7616                         r_refdef.view.cullface_front = GL_FRONT;
7617                         r_refdef.view.cullface_back = GL_BACK;
7618                         // also reverse the view matrix
7619                         Matrix4x4_ConcatScale3(&r_refdef.view.matrix, 1, -1, 1);
7620                         R_RenderView_UpdateViewVectors();
7621                         if(p->camera_entity)
7622                                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
7623                         
7624                         // camera needs no clipplane
7625                         r_refdef.view.useclipplane = false;
7626
7627                         PlaneClassify(&r_refdef.view.clipplane);
7628
7629                         R_ResetViewRendering3D();
7630                         R_ClearScreen(r_refdef.fogenabled);
7631                         R_View_Update();
7632                         R_RenderScene();
7633
7634                         R_Mesh_CopyToTexture(p->texture_camera, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7635                         r_waterstate.renderingrefraction = false;
7636                 }
7637
7638         }
7639         r_waterstate.renderingscene = false;
7640         r_refdef.view = originalview;
7641         R_ResetViewRendering3D();
7642         R_ClearScreen(r_refdef.fogenabled);
7643         R_View_Update();
7644         return;
7645 error:
7646         r_refdef.view = originalview;
7647         r_waterstate.renderingscene = false;
7648         Cvar_SetValueQuick(&r_water, 0);
7649         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
7650         return;
7651 }
7652
7653 void R_Bloom_StartFrame(void)
7654 {
7655         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
7656
7657         switch(vid.renderpath)
7658         {
7659         case RENDERPATH_GL20:
7660         case RENDERPATH_CGGL:
7661                 break;
7662         case RENDERPATH_GL13:
7663         case RENDERPATH_GL11:
7664                 return;
7665         }
7666
7667         // set bloomwidth and bloomheight to the bloom resolution that will be
7668         // used (often less than the screen resolution for faster rendering)
7669         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
7670         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
7671         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
7672         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
7673         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
7674
7675         // calculate desired texture sizes
7676         if (vid.support.arb_texture_non_power_of_two)
7677         {
7678                 screentexturewidth = r_refdef.view.width;
7679                 screentextureheight = r_refdef.view.height;
7680                 bloomtexturewidth = r_bloomstate.bloomwidth;
7681                 bloomtextureheight = r_bloomstate.bloomheight;
7682         }
7683         else
7684         {
7685                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
7686                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
7687                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
7688                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
7689         }
7690
7691         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))
7692         {
7693                 Cvar_SetValueQuick(&r_hdr, 0);
7694                 Cvar_SetValueQuick(&r_bloom, 0);
7695                 Cvar_SetValueQuick(&r_motionblur, 0);
7696                 Cvar_SetValueQuick(&r_damageblur, 0);
7697         }
7698
7699         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)))
7700                 screentexturewidth = screentextureheight = 0;
7701         if (!r_hdr.integer && !r_bloom.integer)
7702                 bloomtexturewidth = bloomtextureheight = 0;
7703
7704         // allocate textures as needed
7705         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
7706         {
7707                 if (r_bloomstate.texture_screen)
7708                         R_FreeTexture(r_bloomstate.texture_screen);
7709                 r_bloomstate.texture_screen = NULL;
7710                 r_bloomstate.screentexturewidth = screentexturewidth;
7711                 r_bloomstate.screentextureheight = screentextureheight;
7712                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
7713                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
7714         }
7715         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
7716         {
7717                 if (r_bloomstate.texture_bloom)
7718                         R_FreeTexture(r_bloomstate.texture_bloom);
7719                 r_bloomstate.texture_bloom = NULL;
7720                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
7721                 r_bloomstate.bloomtextureheight = bloomtextureheight;
7722                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
7723                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7724         }
7725
7726         // when doing a reduced render (HDR) we want to use a smaller area
7727         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
7728         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
7729         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
7730         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
7731         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
7732
7733         // set up a texcoord array for the full resolution screen image
7734         // (we have to keep this around to copy back during final render)
7735         r_bloomstate.screentexcoord2f[0] = 0;
7736         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7737         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7738         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7739         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7740         r_bloomstate.screentexcoord2f[5] = 0;
7741         r_bloomstate.screentexcoord2f[6] = 0;
7742         r_bloomstate.screentexcoord2f[7] = 0;
7743
7744         // set up a texcoord array for the reduced resolution bloom image
7745         // (which will be additive blended over the screen image)
7746         r_bloomstate.bloomtexcoord2f[0] = 0;
7747         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7748         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7749         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7750         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7751         r_bloomstate.bloomtexcoord2f[5] = 0;
7752         r_bloomstate.bloomtexcoord2f[6] = 0;
7753         r_bloomstate.bloomtexcoord2f[7] = 0;
7754
7755         if (r_hdr.integer || r_bloom.integer)
7756         {
7757                 r_bloomstate.enabled = true;
7758                 r_bloomstate.hdr = r_hdr.integer != 0;
7759         }
7760
7761         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);
7762 }
7763
7764 void R_Bloom_CopyBloomTexture(float colorscale)
7765 {
7766         r_refdef.stats.bloom++;
7767
7768         // scale down screen texture to the bloom texture size
7769         CHECKGLERROR
7770         R_SetViewport(&r_bloomstate.viewport);
7771         GL_BlendFunc(GL_ONE, GL_ZERO);
7772         GL_Color(colorscale, colorscale, colorscale, 1);
7773         // TODO: optimize with multitexture or GLSL
7774         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7775         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7776         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7777         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7778
7779         // we now have a bloom image in the framebuffer
7780         // copy it into the bloom image texture for later processing
7781         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);
7782         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7783 }
7784
7785 void R_Bloom_CopyHDRTexture(void)
7786 {
7787         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);
7788         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7789 }
7790
7791 void R_Bloom_MakeTexture(void)
7792 {
7793         int x, range, dir;
7794         float xoffset, yoffset, r, brighten;
7795
7796         r_refdef.stats.bloom++;
7797
7798         R_ResetViewRendering2D();
7799         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7800         R_Mesh_ColorPointer(NULL, 0, 0);
7801
7802         // we have a bloom image in the framebuffer
7803         CHECKGLERROR
7804         R_SetViewport(&r_bloomstate.viewport);
7805
7806         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
7807         {
7808                 x *= 2;
7809                 r = bound(0, r_bloom_colorexponent.value / x, 1);
7810                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7811                 GL_Color(r, r, r, 1);
7812                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7813                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7814                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7815                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7816
7817                 // copy the vertically blurred bloom view to a texture
7818                 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);
7819                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7820         }
7821
7822         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
7823         brighten = r_bloom_brighten.value;
7824         if (r_hdr.integer)
7825                 brighten *= r_hdr_range.value;
7826         brighten = sqrt(brighten);
7827         if(range >= 1)
7828                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
7829         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7830         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
7831
7832         for (dir = 0;dir < 2;dir++)
7833         {
7834                 // blend on at multiple vertical offsets to achieve a vertical blur
7835                 // TODO: do offset blends using GLSL
7836                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
7837                 GL_BlendFunc(GL_ONE, GL_ZERO);
7838                 for (x = -range;x <= range;x++)
7839                 {
7840                         if (!dir){xoffset = 0;yoffset = x;}
7841                         else {xoffset = x;yoffset = 0;}
7842                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
7843                         yoffset /= (float)r_bloomstate.bloomtextureheight;
7844                         // compute a texcoord array with the specified x and y offset
7845                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
7846                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7847                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7848                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7849                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7850                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
7851                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
7852                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
7853                         // this r value looks like a 'dot' particle, fading sharply to
7854                         // black at the edges
7855                         // (probably not realistic but looks good enough)
7856                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
7857                         //r = brighten/(range*2+1);
7858                         r = brighten / (range * 2 + 1);
7859                         if(range >= 1)
7860                                 r *= (1 - x*x/(float)(range*range));
7861                         GL_Color(r, r, r, 1);
7862                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7863                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7864                         GL_BlendFunc(GL_ONE, GL_ONE);
7865                 }
7866
7867                 // copy the vertically blurred bloom view to a texture
7868                 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);
7869                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7870         }
7871
7872         // apply subtract last
7873         // (just like it would be in a GLSL shader)
7874         if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
7875         {
7876                 GL_BlendFunc(GL_ONE, GL_ZERO);
7877                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7878                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7879                 GL_Color(1, 1, 1, 1);
7880                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7881                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7882
7883                 GL_BlendFunc(GL_ONE, GL_ONE);
7884                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
7885                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7886                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7887                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
7888                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7889                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7890                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
7891
7892                 // copy the darkened bloom view to a texture
7893                 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);
7894                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7895         }
7896 }
7897
7898 void R_HDR_RenderBloomTexture(void)
7899 {
7900         int oldwidth, oldheight;
7901         float oldcolorscale;
7902
7903         oldcolorscale = r_refdef.view.colorscale;
7904         oldwidth = r_refdef.view.width;
7905         oldheight = r_refdef.view.height;
7906         r_refdef.view.width = r_bloomstate.bloomwidth;
7907         r_refdef.view.height = r_bloomstate.bloomheight;
7908
7909         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
7910         // TODO: add exposure compensation features
7911         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
7912
7913         r_refdef.view.showdebug = false;
7914         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
7915
7916         R_ResetViewRendering3D();
7917
7918         R_ClearScreen(r_refdef.fogenabled);
7919         if (r_timereport_active)
7920                 R_TimeReport("HDRclear");
7921
7922         R_View_Update();
7923         if (r_timereport_active)
7924                 R_TimeReport("visibility");
7925
7926         // only do secondary renders with HDR if r_hdr is 2 or higher
7927         r_waterstate.numwaterplanes = 0;
7928         if (r_waterstate.enabled && r_hdr.integer >= 2)
7929                 R_RenderWaterPlanes();
7930
7931         r_refdef.view.showdebug = true;
7932         R_RenderScene();
7933         r_waterstate.numwaterplanes = 0;
7934
7935         R_ResetViewRendering2D();
7936
7937         R_Bloom_CopyHDRTexture();
7938         R_Bloom_MakeTexture();
7939
7940         // restore the view settings
7941         r_refdef.view.width = oldwidth;
7942         r_refdef.view.height = oldheight;
7943         r_refdef.view.colorscale = oldcolorscale;
7944
7945         R_ResetViewRendering3D();
7946
7947         R_ClearScreen(r_refdef.fogenabled);
7948         if (r_timereport_active)
7949                 R_TimeReport("viewclear");
7950 }
7951
7952 static void R_BlendView(void)
7953 {
7954         unsigned int permutation;
7955         float uservecs[4][4];
7956
7957         switch (vid.renderpath)
7958         {
7959         case RENDERPATH_GL20:
7960         case RENDERPATH_CGGL:
7961                 permutation =
7962                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
7963                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
7964                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
7965                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
7966                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
7967
7968                 if (r_bloomstate.texture_screen)
7969                 {
7970                         // make sure the buffer is available
7971                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
7972
7973                         R_ResetViewRendering2D();
7974                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7975                         R_Mesh_ColorPointer(NULL, 0, 0);
7976
7977                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
7978                         {
7979                                 // declare variables
7980                                 float speed;
7981                                 static float avgspeed;
7982
7983                                 speed = VectorLength(cl.movement_velocity);
7984
7985                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
7986                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
7987
7988                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
7989                                 speed = bound(0, speed, 1);
7990                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
7991
7992                                 // calculate values into a standard alpha
7993                                 cl.motionbluralpha = 1 - exp(-
7994                                                 (
7995                                                  (r_motionblur.value * speed / 80)
7996                                                  +
7997                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
7998                                                 )
7999                                                 /
8000                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
8001                                            );
8002
8003                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
8004                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
8005                                 // apply the blur
8006                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
8007                                 {
8008                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8009                                         GL_Color(1, 1, 1, cl.motionbluralpha);
8010                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8011                                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
8012                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8013                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8014                                 }
8015                         }
8016
8017                         // copy view into the screen texture
8018                         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);
8019                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8020                 }
8021                 else if (!r_bloomstate.texture_bloom)
8022                 {
8023                         // we may still have to do view tint...
8024                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8025                         {
8026                                 // apply a color tint to the whole view
8027                                 R_ResetViewRendering2D();
8028                                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
8029                                 R_Mesh_ColorPointer(NULL, 0, 0);
8030                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8031                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8032                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8033                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8034                         }
8035                         break; // no screen processing, no bloom, skip it
8036                 }
8037
8038                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
8039                 {
8040                         // render simple bloom effect
8041                         // copy the screen and shrink it and darken it for the bloom process
8042                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
8043                         // make the bloom texture
8044                         R_Bloom_MakeTexture();
8045                 }
8046
8047 #if _MSC_VER >= 1400
8048 #define sscanf sscanf_s
8049 #endif
8050                 memset(uservecs, 0, sizeof(uservecs));
8051                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
8052                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
8053                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
8054                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
8055
8056                 R_ResetViewRendering2D();
8057                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
8058                 R_Mesh_ColorPointer(NULL, 0, 0);
8059                 GL_Color(1, 1, 1, 1);
8060                 GL_BlendFunc(GL_ONE, GL_ZERO);
8061                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
8062                 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
8063
8064                 switch(vid.renderpath)
8065                 {
8066                 case RENDERPATH_GL20:
8067                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
8068                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
8069                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
8070                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
8071                         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]);
8072                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8073                         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]);
8074                         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]);
8075                         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]);
8076                         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]);
8077                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
8078                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
8079                         break;
8080                 case RENDERPATH_CGGL:
8081 #ifdef SUPPORTCG
8082                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
8083                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
8084                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
8085                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
8086                         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
8087                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
8088                         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
8089                         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
8090                         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
8091                         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
8092                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
8093                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
8094 #endif
8095                         break;
8096                 default:
8097                         break;
8098                 }
8099                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8100                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8101                 break;
8102         case RENDERPATH_GL13:
8103         case RENDERPATH_GL11:
8104                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8105                 {
8106                         // apply a color tint to the whole view
8107                         R_ResetViewRendering2D();
8108                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
8109                         R_Mesh_ColorPointer(NULL, 0, 0);
8110                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8111                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8112                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8113                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8114                 }
8115                 break;
8116         }
8117 }
8118
8119 matrix4x4_t r_waterscrollmatrix;
8120
8121 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
8122 {
8123         if (r_refdef.fog_density)
8124         {
8125                 r_refdef.fogcolor[0] = r_refdef.fog_red;
8126                 r_refdef.fogcolor[1] = r_refdef.fog_green;
8127                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
8128
8129                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
8130                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
8131                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
8132                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
8133
8134                 {
8135                         vec3_t fogvec;
8136                         VectorCopy(r_refdef.fogcolor, fogvec);
8137                         //   color.rgb *= ContrastBoost * SceneBrightness;
8138                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
8139                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
8140                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
8141                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
8142                 }
8143         }
8144 }
8145
8146 void R_UpdateVariables(void)
8147 {
8148         R_Textures_Frame();
8149
8150         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
8151
8152         r_refdef.farclip = r_farclip_base.value;
8153         if (r_refdef.scene.worldmodel)
8154                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
8155         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
8156
8157         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
8158                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
8159         r_refdef.polygonfactor = 0;
8160         r_refdef.polygonoffset = 0;
8161         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8162         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8163
8164         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
8165         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
8166         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
8167         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
8168         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
8169         if (r_showsurfaces.integer)
8170         {
8171                 r_refdef.scene.rtworld = false;
8172                 r_refdef.scene.rtworldshadows = false;
8173                 r_refdef.scene.rtdlight = false;
8174                 r_refdef.scene.rtdlightshadows = false;
8175                 r_refdef.lightmapintensity = 0;
8176         }
8177
8178         if (gamemode == GAME_NEHAHRA)
8179         {
8180                 if (gl_fogenable.integer)
8181                 {
8182                         r_refdef.oldgl_fogenable = true;
8183                         r_refdef.fog_density = gl_fogdensity.value;
8184                         r_refdef.fog_red = gl_fogred.value;
8185                         r_refdef.fog_green = gl_foggreen.value;
8186                         r_refdef.fog_blue = gl_fogblue.value;
8187                         r_refdef.fog_alpha = 1;
8188                         r_refdef.fog_start = 0;
8189                         r_refdef.fog_end = gl_skyclip.value;
8190                         r_refdef.fog_height = 1<<30;
8191                         r_refdef.fog_fadedepth = 128;
8192                 }
8193                 else if (r_refdef.oldgl_fogenable)
8194                 {
8195                         r_refdef.oldgl_fogenable = false;
8196                         r_refdef.fog_density = 0;
8197                         r_refdef.fog_red = 0;
8198                         r_refdef.fog_green = 0;
8199                         r_refdef.fog_blue = 0;
8200                         r_refdef.fog_alpha = 0;
8201                         r_refdef.fog_start = 0;
8202                         r_refdef.fog_end = 0;
8203                         r_refdef.fog_height = 1<<30;
8204                         r_refdef.fog_fadedepth = 128;
8205                 }
8206         }
8207
8208         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
8209         r_refdef.fog_start = max(0, r_refdef.fog_start);
8210         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
8211
8212         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
8213
8214         if (r_refdef.fog_density && r_drawfog.integer)
8215         {
8216                 r_refdef.fogenabled = true;
8217                 // this is the point where the fog reaches 0.9986 alpha, which we
8218                 // consider a good enough cutoff point for the texture
8219                 // (0.9986 * 256 == 255.6)
8220                 if (r_fog_exp2.integer)
8221                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
8222                 else
8223                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
8224                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
8225                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
8226                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
8227                 // fog color was already set
8228                 // update the fog texture
8229                 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)
8230                         R_BuildFogTexture();
8231         }
8232         else
8233                 r_refdef.fogenabled = false;
8234
8235         switch(vid.renderpath)
8236         {
8237         case RENDERPATH_GL20:
8238         case RENDERPATH_CGGL:
8239                 if(v_glslgamma.integer && !vid_gammatables_trivial)
8240                 {
8241                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
8242                         {
8243                                 // build GLSL gamma texture
8244 #define RAMPWIDTH 256
8245                                 unsigned short ramp[RAMPWIDTH * 3];
8246                                 unsigned char rampbgr[RAMPWIDTH][4];
8247                                 int i;
8248
8249                                 r_texture_gammaramps_serial = vid_gammatables_serial;
8250
8251                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
8252                                 for(i = 0; i < RAMPWIDTH; ++i)
8253                                 {
8254                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8255                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8256                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
8257                                         rampbgr[i][3] = 0;
8258                                 }
8259                                 if (r_texture_gammaramps)
8260                                 {
8261                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
8262                                 }
8263                                 else
8264                                 {
8265                                         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);
8266                                 }
8267                         }
8268                 }
8269                 else
8270                 {
8271                         // remove GLSL gamma texture
8272                 }
8273                 break;
8274         case RENDERPATH_GL13:
8275         case RENDERPATH_GL11:
8276                 break;
8277         }
8278 }
8279
8280 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
8281 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
8282 /*
8283 ================
8284 R_SelectScene
8285 ================
8286 */
8287 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
8288         if( scenetype != r_currentscenetype ) {
8289                 // store the old scenetype
8290                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
8291                 r_currentscenetype = scenetype;
8292                 // move in the new scene
8293                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
8294         }
8295 }
8296
8297 /*
8298 ================
8299 R_GetScenePointer
8300 ================
8301 */
8302 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
8303 {
8304         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
8305         if( scenetype == r_currentscenetype ) {
8306                 return &r_refdef.scene;
8307         } else {
8308                 return &r_scenes_store[ scenetype ];
8309         }
8310 }
8311
8312 /*
8313 ================
8314 R_RenderView
8315 ================
8316 */
8317 void R_RenderView(void)
8318 {
8319         if (r_timereport_active)
8320                 R_TimeReport("start");
8321         r_textureframe++; // used only by R_GetCurrentTexture
8322         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8323
8324         if (!r_drawentities.integer)
8325                 r_refdef.scene.numentities = 0;
8326
8327         R_AnimCache_ClearCache();
8328         R_FrameData_NewFrame();
8329
8330         if (r_refdef.view.isoverlay)
8331         {
8332                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
8333                 GL_Clear( GL_DEPTH_BUFFER_BIT );
8334                 R_TimeReport("depthclear");
8335
8336                 r_refdef.view.showdebug = false;
8337
8338                 r_waterstate.enabled = false;
8339                 r_waterstate.numwaterplanes = 0;
8340
8341                 R_RenderScene();
8342
8343                 CHECKGLERROR
8344                 return;
8345         }
8346
8347         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
8348                 return; //Host_Error ("R_RenderView: NULL worldmodel");
8349
8350         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
8351
8352         R_RenderView_UpdateViewVectors();
8353
8354         R_Shadow_UpdateWorldLightSelection();
8355
8356         R_Bloom_StartFrame();
8357         R_Water_StartFrame();
8358
8359         CHECKGLERROR
8360         if (r_timereport_active)
8361                 R_TimeReport("viewsetup");
8362
8363         R_ResetViewRendering3D();
8364
8365         if (r_refdef.view.clear || r_refdef.fogenabled)
8366         {
8367                 R_ClearScreen(r_refdef.fogenabled);
8368                 if (r_timereport_active)
8369                         R_TimeReport("viewclear");
8370         }
8371         r_refdef.view.clear = true;
8372
8373         // this produces a bloom texture to be used in R_BlendView() later
8374         if (r_hdr.integer && r_bloomstate.bloomwidth)
8375         {
8376                 R_HDR_RenderBloomTexture();
8377                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
8378                 r_textureframe++; // used only by R_GetCurrentTexture
8379         }
8380
8381         r_refdef.view.showdebug = true;
8382
8383         R_View_Update();
8384         if (r_timereport_active)
8385                 R_TimeReport("visibility");
8386
8387         r_waterstate.numwaterplanes = 0;
8388         if (r_waterstate.enabled)
8389                 R_RenderWaterPlanes();
8390
8391         R_RenderScene();
8392         r_waterstate.numwaterplanes = 0;
8393
8394         R_BlendView();
8395         if (r_timereport_active)
8396                 R_TimeReport("blendview");
8397
8398         GL_Scissor(0, 0, vid.width, vid.height);
8399         GL_ScissorTest(false);
8400         CHECKGLERROR
8401 }
8402
8403 void R_RenderWaterPlanes(void)
8404 {
8405         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
8406         {
8407                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
8408                 if (r_timereport_active)
8409                         R_TimeReport("waterworld");
8410         }
8411
8412         // don't let sound skip if going slow
8413         if (r_refdef.scene.extraupdate)
8414                 S_ExtraUpdate ();
8415
8416         R_DrawModelsAddWaterPlanes();
8417         if (r_timereport_active)
8418                 R_TimeReport("watermodels");
8419
8420         if (r_waterstate.numwaterplanes)
8421         {
8422                 R_Water_ProcessPlanes();
8423                 if (r_timereport_active)
8424                         R_TimeReport("waterscenes");
8425         }
8426 }
8427
8428 extern void R_DrawLightningBeams (void);
8429 extern void VM_CL_AddPolygonsToMeshQueue (void);
8430 extern void R_DrawPortals (void);
8431 extern cvar_t cl_locs_show;
8432 static void R_DrawLocs(void);
8433 static void R_DrawEntityBBoxes(void);
8434 static void R_DrawModelDecals(void);
8435 extern void R_DrawModelShadows(void);
8436 extern void R_DrawModelShadowMaps(void);
8437 extern cvar_t cl_decals_newsystem;
8438 extern qboolean r_shadow_usingdeferredprepass;
8439 void R_RenderScene(void)
8440 {
8441         qboolean shadowmapping = false;
8442
8443         if (r_timereport_active)
8444                 R_TimeReport("beginscene");
8445
8446         r_refdef.stats.renders++;
8447
8448         R_UpdateFogColor();
8449
8450         // don't let sound skip if going slow
8451         if (r_refdef.scene.extraupdate)
8452                 S_ExtraUpdate ();
8453
8454         R_MeshQueue_BeginScene();
8455
8456         R_SkyStartFrame();
8457
8458         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);
8459
8460         if (r_timereport_active)
8461                 R_TimeReport("skystartframe");
8462
8463         if (cl.csqc_vidvars.drawworld)
8464         {
8465                 // don't let sound skip if going slow
8466                 if (r_refdef.scene.extraupdate)
8467                         S_ExtraUpdate ();
8468
8469                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
8470                 {
8471                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
8472                         if (r_timereport_active)
8473                                 R_TimeReport("worldsky");
8474                 }
8475
8476                 if (R_DrawBrushModelsSky() && r_timereport_active)
8477                         R_TimeReport("bmodelsky");
8478
8479                 if (skyrendermasked && skyrenderlater)
8480                 {
8481                         // we have to force off the water clipping plane while rendering sky
8482                         R_SetupView(false);
8483                         R_Sky();
8484                         R_SetupView(true);
8485                         if (r_timereport_active)
8486                                 R_TimeReport("sky");
8487                 }
8488         }
8489
8490         R_AnimCache_CacheVisibleEntities();
8491         if (r_timereport_active)
8492                 R_TimeReport("animation");
8493
8494         R_Shadow_PrepareLights();
8495         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
8496                 R_Shadow_PrepareModelShadows();
8497         if (r_timereport_active)
8498                 R_TimeReport("preparelights");
8499
8500         if (R_Shadow_ShadowMappingEnabled())
8501                 shadowmapping = true;
8502
8503         if (r_shadow_usingdeferredprepass)
8504                 R_Shadow_DrawPrepass();
8505
8506         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
8507         {
8508                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
8509                 if (r_timereport_active)
8510                         R_TimeReport("worlddepth");
8511         }
8512         if (r_depthfirst.integer >= 2)
8513         {
8514                 R_DrawModelsDepth();
8515                 if (r_timereport_active)
8516                         R_TimeReport("modeldepth");
8517         }
8518
8519         if (r_shadows.integer > 0 && shadowmapping && r_refdef.lightmapintensity > 0)
8520         {
8521                 R_DrawModelShadowMaps();
8522                 R_ResetViewRendering3D();
8523                 // don't let sound skip if going slow
8524                 if (r_refdef.scene.extraupdate)
8525                         S_ExtraUpdate ();
8526         }
8527
8528         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
8529         {
8530                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
8531                 if (r_timereport_active)
8532                         R_TimeReport("world");
8533         }
8534
8535         // don't let sound skip if going slow
8536         if (r_refdef.scene.extraupdate)
8537                 S_ExtraUpdate ();
8538
8539         R_DrawModels();
8540         if (r_timereport_active)
8541                 R_TimeReport("models");
8542
8543         // don't let sound skip if going slow
8544         if (r_refdef.scene.extraupdate)
8545                 S_ExtraUpdate ();
8546
8547         if (r_shadows.integer > 0 && !shadowmapping && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8548         {
8549                 R_DrawModelShadows();
8550                 R_ResetViewRendering3D();
8551                 // don't let sound skip if going slow
8552                 if (r_refdef.scene.extraupdate)
8553                         S_ExtraUpdate ();
8554         }
8555
8556         if (!r_shadow_usingdeferredprepass)
8557         {
8558                 R_Shadow_DrawLights();
8559                 if (r_timereport_active)
8560                         R_TimeReport("rtlights");
8561         }
8562
8563         // don't let sound skip if going slow
8564         if (r_refdef.scene.extraupdate)
8565                 S_ExtraUpdate ();
8566
8567         if (r_shadows.integer > 0 && !shadowmapping && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8568         {
8569                 R_DrawModelShadows();
8570                 R_ResetViewRendering3D();
8571                 // don't let sound skip if going slow
8572                 if (r_refdef.scene.extraupdate)
8573                         S_ExtraUpdate ();
8574         }
8575
8576         if (cl.csqc_vidvars.drawworld)
8577         {
8578                 if (cl_decals_newsystem.integer)
8579                 {
8580                         R_DrawModelDecals();
8581                         if (r_timereport_active)
8582                                 R_TimeReport("modeldecals");
8583                 }
8584                 else
8585                 {
8586                         R_DrawDecals();
8587                         if (r_timereport_active)
8588                                 R_TimeReport("decals");
8589                 }
8590
8591                 R_DrawParticles();
8592                 if (r_timereport_active)
8593                         R_TimeReport("particles");
8594
8595                 R_DrawExplosions();
8596                 if (r_timereport_active)
8597                         R_TimeReport("explosions");
8598
8599                 R_DrawLightningBeams();
8600                 if (r_timereport_active)
8601                         R_TimeReport("lightning");
8602         }
8603
8604         VM_CL_AddPolygonsToMeshQueue();
8605
8606         if (r_refdef.view.showdebug)
8607         {
8608                 if (cl_locs_show.integer)
8609                 {
8610                         R_DrawLocs();
8611                         if (r_timereport_active)
8612                                 R_TimeReport("showlocs");
8613                 }
8614
8615                 if (r_drawportals.integer)
8616                 {
8617                         R_DrawPortals();
8618                         if (r_timereport_active)
8619                                 R_TimeReport("portals");
8620                 }
8621
8622                 if (r_showbboxes.value > 0)
8623                 {
8624                         R_DrawEntityBBoxes();
8625                         if (r_timereport_active)
8626                                 R_TimeReport("bboxes");
8627                 }
8628         }
8629
8630         R_MeshQueue_RenderTransparent();
8631         if (r_timereport_active)
8632                 R_TimeReport("drawtrans");
8633
8634         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))
8635         {
8636                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
8637                 if (r_timereport_active)
8638                         R_TimeReport("worlddebug");
8639                 R_DrawModelsDebug();
8640                 if (r_timereport_active)
8641                         R_TimeReport("modeldebug");
8642         }
8643
8644         if (cl.csqc_vidvars.drawworld)
8645         {
8646                 R_Shadow_DrawCoronas();
8647                 if (r_timereport_active)
8648                         R_TimeReport("coronas");
8649         }
8650
8651         // don't let sound skip if going slow
8652         if (r_refdef.scene.extraupdate)
8653                 S_ExtraUpdate ();
8654
8655         R_ResetViewRendering2D();
8656 }
8657
8658 static const unsigned short bboxelements[36] =
8659 {
8660         5, 1, 3, 5, 3, 7,
8661         6, 2, 0, 6, 0, 4,
8662         7, 3, 2, 7, 2, 6,
8663         4, 0, 1, 4, 1, 5,
8664         4, 5, 7, 4, 7, 6,
8665         1, 0, 2, 1, 2, 3,
8666 };
8667
8668 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
8669 {
8670         int i;
8671         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
8672
8673         RSurf_ActiveWorldEntity();
8674
8675         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8676         GL_DepthMask(false);
8677         GL_DepthRange(0, 1);
8678         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8679         R_Mesh_ResetTextureState();
8680
8681         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
8682         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
8683         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
8684         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
8685         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
8686         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
8687         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
8688         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
8689         R_FillColors(color4f, 8, cr, cg, cb, ca);
8690         if (r_refdef.fogenabled)
8691         {
8692                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
8693                 {
8694                         f1 = RSurf_FogVertex(v);
8695                         f2 = 1 - f1;
8696                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
8697                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
8698                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
8699                 }
8700         }
8701         R_Mesh_VertexPointer(vertex3f, 0, 0);
8702         R_Mesh_ColorPointer(color4f, 0, 0);
8703         R_Mesh_ResetTextureState();
8704         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8705         R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
8706 }
8707
8708 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8709 {
8710         int i;
8711         float color[4];
8712         prvm_edict_t *edict;
8713         prvm_prog_t *prog_save = prog;
8714
8715         // this function draws bounding boxes of server entities
8716         if (!sv.active)
8717                 return;
8718
8719         GL_CullFace(GL_NONE);
8720         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8721
8722         prog = 0;
8723         SV_VM_Begin();
8724         for (i = 0;i < numsurfaces;i++)
8725         {
8726                 edict = PRVM_EDICT_NUM(surfacelist[i]);
8727                 switch ((int)edict->fields.server->solid)
8728                 {
8729                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
8730                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
8731                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
8732                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
8733                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
8734                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
8735                 }
8736                 color[3] *= r_showbboxes.value;
8737                 color[3] = bound(0, color[3], 1);
8738                 GL_DepthTest(!r_showdisabledepthtest.integer);
8739                 GL_CullFace(r_refdef.view.cullface_front);
8740                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
8741         }
8742         SV_VM_End();
8743         prog = prog_save;
8744 }
8745
8746 static void R_DrawEntityBBoxes(void)
8747 {
8748         int i;
8749         prvm_edict_t *edict;
8750         vec3_t center;
8751         prvm_prog_t *prog_save = prog;
8752
8753         // this function draws bounding boxes of server entities
8754         if (!sv.active)
8755                 return;
8756
8757         prog = 0;
8758         SV_VM_Begin();
8759         for (i = 0;i < prog->num_edicts;i++)
8760         {
8761                 edict = PRVM_EDICT_NUM(i);
8762                 if (edict->priv.server->free)
8763                         continue;
8764                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
8765                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
8766                         continue;
8767                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
8768                         continue;
8769                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
8770                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
8771         }
8772         SV_VM_End();
8773         prog = prog_save;
8774 }
8775
8776 static const int nomodelelement3i[24] =
8777 {
8778         5, 2, 0,
8779         5, 1, 2,
8780         5, 0, 3,
8781         5, 3, 1,
8782         0, 2, 4,
8783         2, 1, 4,
8784         3, 0, 4,
8785         1, 3, 4
8786 };
8787
8788 static const unsigned short nomodelelement3s[24] =
8789 {
8790         5, 2, 0,
8791         5, 1, 2,
8792         5, 0, 3,
8793         5, 3, 1,
8794         0, 2, 4,
8795         2, 1, 4,
8796         3, 0, 4,
8797         1, 3, 4
8798 };
8799
8800 static const float nomodelvertex3f[6*3] =
8801 {
8802         -16,   0,   0,
8803          16,   0,   0,
8804           0, -16,   0,
8805           0,  16,   0,
8806           0,   0, -16,
8807           0,   0,  16
8808 };
8809
8810 static const float nomodelcolor4f[6*4] =
8811 {
8812         0.0f, 0.0f, 0.5f, 1.0f,
8813         0.0f, 0.0f, 0.5f, 1.0f,
8814         0.0f, 0.5f, 0.0f, 1.0f,
8815         0.0f, 0.5f, 0.0f, 1.0f,
8816         0.5f, 0.0f, 0.0f, 1.0f,
8817         0.5f, 0.0f, 0.0f, 1.0f
8818 };
8819
8820 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8821 {
8822         int i;
8823         float f1, f2, *c;
8824         float color4f[6*4];
8825
8826         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);
8827
8828         // this is only called once per entity so numsurfaces is always 1, and
8829         // surfacelist is always {0}, so this code does not handle batches
8830
8831         if (rsurface.ent_flags & RENDER_ADDITIVE)
8832         {
8833                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
8834                 GL_DepthMask(false);
8835         }
8836         else if (rsurface.colormod[3] < 1)
8837         {
8838                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8839                 GL_DepthMask(false);
8840         }
8841         else
8842         {
8843                 GL_BlendFunc(GL_ONE, GL_ZERO);
8844                 GL_DepthMask(true);
8845         }
8846         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8847         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8848         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8849         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8850         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8851         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
8852         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8853         R_Mesh_ColorPointer(color4f, 0, 0);
8854         for (i = 0, c = color4f;i < 6;i++, c += 4)
8855         {
8856                 c[0] *= rsurface.colormod[0];
8857                 c[1] *= rsurface.colormod[1];
8858                 c[2] *= rsurface.colormod[2];
8859                 c[3] *= rsurface.colormod[3];
8860         }
8861         if (r_refdef.fogenabled)
8862         {
8863                 for (i = 0, c = color4f;i < 6;i++, c += 4)
8864                 {
8865                         f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
8866                         f2 = 1 - f1;
8867                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8868                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8869                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8870                 }
8871         }
8872         R_Mesh_ResetTextureState();
8873         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
8874 }
8875
8876 void R_DrawNoModel(entity_render_t *ent)
8877 {
8878         vec3_t org;
8879         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8880         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8881                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8882         else
8883                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8884 }
8885
8886 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8887 {
8888         vec3_t right1, right2, diff, normal;
8889
8890         VectorSubtract (org2, org1, normal);
8891
8892         // calculate 'right' vector for start
8893         VectorSubtract (r_refdef.view.origin, org1, diff);
8894         CrossProduct (normal, diff, right1);
8895         VectorNormalize (right1);
8896
8897         // calculate 'right' vector for end
8898         VectorSubtract (r_refdef.view.origin, org2, diff);
8899         CrossProduct (normal, diff, right2);
8900         VectorNormalize (right2);
8901
8902         vert[ 0] = org1[0] + width * right1[0];
8903         vert[ 1] = org1[1] + width * right1[1];
8904         vert[ 2] = org1[2] + width * right1[2];
8905         vert[ 3] = org1[0] - width * right1[0];
8906         vert[ 4] = org1[1] - width * right1[1];
8907         vert[ 5] = org1[2] - width * right1[2];
8908         vert[ 6] = org2[0] - width * right2[0];
8909         vert[ 7] = org2[1] - width * right2[1];
8910         vert[ 8] = org2[2] - width * right2[2];
8911         vert[ 9] = org2[0] + width * right2[0];
8912         vert[10] = org2[1] + width * right2[1];
8913         vert[11] = org2[2] + width * right2[2];
8914 }
8915
8916 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)
8917 {
8918         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8919         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8920         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8921         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8922         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8923         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8924         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8925         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8926         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8927         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8928         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8929         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8930 }
8931
8932 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8933 {
8934         int i;
8935         float *vertex3f;
8936         float v[3];
8937         VectorSet(v, x, y, z);
8938         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8939                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8940                         break;
8941         if (i == mesh->numvertices)
8942         {
8943                 if (mesh->numvertices < mesh->maxvertices)
8944                 {
8945                         VectorCopy(v, vertex3f);
8946                         mesh->numvertices++;
8947                 }
8948                 return mesh->numvertices;
8949         }
8950         else
8951                 return i;
8952 }
8953
8954 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8955 {
8956         int i;
8957         int *e, element[3];
8958         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8959         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8960         e = mesh->element3i + mesh->numtriangles * 3;
8961         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8962         {
8963                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8964                 if (mesh->numtriangles < mesh->maxtriangles)
8965                 {
8966                         *e++ = element[0];
8967                         *e++ = element[1];
8968                         *e++ = element[2];
8969                         mesh->numtriangles++;
8970                 }
8971                 element[1] = element[2];
8972         }
8973 }
8974
8975 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8976 {
8977         int i;
8978         int *e, element[3];
8979         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8980         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8981         e = mesh->element3i + mesh->numtriangles * 3;
8982         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8983         {
8984                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8985                 if (mesh->numtriangles < mesh->maxtriangles)
8986                 {
8987                         *e++ = element[0];
8988                         *e++ = element[1];
8989                         *e++ = element[2];
8990                         mesh->numtriangles++;
8991                 }
8992                 element[1] = element[2];
8993         }
8994 }
8995
8996 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8997 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8998 {
8999         int planenum, planenum2;
9000         int w;
9001         int tempnumpoints;
9002         mplane_t *plane, *plane2;
9003         double maxdist;
9004         double temppoints[2][256*3];
9005         // figure out how large a bounding box we need to properly compute this brush
9006         maxdist = 0;
9007         for (w = 0;w < numplanes;w++)
9008                 maxdist = max(maxdist, fabs(planes[w].dist));
9009         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
9010         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
9011         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
9012         {
9013                 w = 0;
9014                 tempnumpoints = 4;
9015                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
9016                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
9017                 {
9018                         if (planenum2 == planenum)
9019                                 continue;
9020                         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);
9021                         w = !w;
9022                 }
9023                 if (tempnumpoints < 3)
9024                         continue;
9025                 // generate elements forming a triangle fan for this polygon
9026                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
9027         }
9028 }
9029
9030 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)
9031 {
9032         texturelayer_t *layer;
9033         layer = t->currentlayers + t->currentnumlayers++;
9034         layer->type = type;
9035         layer->depthmask = depthmask;
9036         layer->blendfunc1 = blendfunc1;
9037         layer->blendfunc2 = blendfunc2;
9038         layer->texture = texture;
9039         layer->texmatrix = *matrix;
9040         layer->color[0] = r;
9041         layer->color[1] = g;
9042         layer->color[2] = b;
9043         layer->color[3] = a;
9044 }
9045
9046 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
9047 {
9048         double index, f;
9049         index = parms[2] + r_refdef.scene.time * parms[3];
9050         index -= floor(index);
9051         switch (func)
9052         {
9053         default:
9054         case Q3WAVEFUNC_NONE:
9055         case Q3WAVEFUNC_NOISE:
9056         case Q3WAVEFUNC_COUNT:
9057                 f = 0;
9058                 break;
9059         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
9060         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
9061         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
9062         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
9063         case Q3WAVEFUNC_TRIANGLE:
9064                 index *= 4;
9065                 f = index - floor(index);
9066                 if (index < 1)
9067                         f = f;
9068                 else if (index < 2)
9069                         f = 1 - f;
9070                 else if (index < 3)
9071                         f = -f;
9072                 else
9073                         f = -(1 - f);
9074                 break;
9075         }
9076         return (float)(parms[0] + parms[1] * f);
9077 }
9078
9079 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
9080 {
9081         int w, h, idx;
9082         float f;
9083         float tcmat[12];
9084         matrix4x4_t matrix, temp;
9085         switch(tcmod->tcmod)
9086         {
9087                 case Q3TCMOD_COUNT:
9088                 case Q3TCMOD_NONE:
9089                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9090                                 matrix = r_waterscrollmatrix;
9091                         else
9092                                 matrix = identitymatrix;
9093                         break;
9094                 case Q3TCMOD_ENTITYTRANSLATE:
9095                         // this is used in Q3 to allow the gamecode to control texcoord
9096                         // scrolling on the entity, which is not supported in darkplaces yet.
9097                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
9098                         break;
9099                 case Q3TCMOD_ROTATE:
9100                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
9101                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
9102                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
9103                         break;
9104                 case Q3TCMOD_SCALE:
9105                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
9106                         break;
9107                 case Q3TCMOD_SCROLL:
9108                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
9109                         break;
9110                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
9111                         w = (int) tcmod->parms[0];
9112                         h = (int) tcmod->parms[1];
9113                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
9114                         f = f - floor(f);
9115                         idx = (int) floor(f * w * h);
9116                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
9117                         break;
9118                 case Q3TCMOD_STRETCH:
9119                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
9120                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
9121                         break;
9122                 case Q3TCMOD_TRANSFORM:
9123                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
9124                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
9125                         VectorSet(tcmat +  6, 0                   , 0                , 1);
9126                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
9127                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
9128                         break;
9129                 case Q3TCMOD_TURBULENT:
9130                         // this is handled in the RSurf_PrepareVertices function
9131                         matrix = identitymatrix;
9132                         break;
9133         }
9134         temp = *texmatrix;
9135         Matrix4x4_Concat(texmatrix, &matrix, &temp);
9136 }
9137
9138 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
9139 {
9140         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
9141         char name[MAX_QPATH];
9142         skinframe_t *skinframe;
9143         unsigned char pixels[296*194];
9144         strlcpy(cache->name, skinname, sizeof(cache->name));
9145         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
9146         if (developer_loading.integer)
9147                 Con_Printf("loading %s\n", name);
9148         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
9149         if (!skinframe || !skinframe->base)
9150         {
9151                 unsigned char *f;
9152                 fs_offset_t filesize;
9153                 skinframe = NULL;
9154                 f = FS_LoadFile(name, tempmempool, true, &filesize);
9155                 if (f)
9156                 {
9157                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
9158                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
9159                         Mem_Free(f);
9160                 }
9161         }
9162         cache->skinframe = skinframe;
9163 }
9164
9165 texture_t *R_GetCurrentTexture(texture_t *t)
9166 {
9167         int i;
9168         const entity_render_t *ent = rsurface.entity;
9169         dp_model_t *model = ent->model;
9170         q3shaderinfo_layer_tcmod_t *tcmod;
9171
9172         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
9173                 return t->currentframe;
9174         t->update_lastrenderframe = r_textureframe;
9175         t->update_lastrenderentity = (void *)ent;
9176
9177         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
9178                 t->camera_entity = ent->entitynumber;
9179         else
9180                 t->camera_entity = 0;
9181
9182         // switch to an alternate material if this is a q1bsp animated material
9183         {
9184                 texture_t *texture = t;
9185                 int s = rsurface.ent_skinnum;
9186                 if ((unsigned int)s >= (unsigned int)model->numskins)
9187                         s = 0;
9188                 if (model->skinscenes)
9189                 {
9190                         if (model->skinscenes[s].framecount > 1)
9191                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
9192                         else
9193                                 s = model->skinscenes[s].firstframe;
9194                 }
9195                 if (s > 0)
9196                         t = t + s * model->num_surfaces;
9197                 if (t->animated)
9198                 {
9199                         // use an alternate animation if the entity's frame is not 0,
9200                         // and only if the texture has an alternate animation
9201                         if (rsurface.ent_alttextures && t->anim_total[1])
9202                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
9203                         else
9204                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
9205                 }
9206                 texture->currentframe = t;
9207         }
9208
9209         // update currentskinframe to be a qw skin or animation frame
9210         if (rsurface.ent_qwskin >= 0)
9211         {
9212                 i = rsurface.ent_qwskin;
9213                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
9214                 {
9215                         r_qwskincache_size = cl.maxclients;
9216                         if (r_qwskincache)
9217                                 Mem_Free(r_qwskincache);
9218                         r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
9219                 }
9220                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
9221                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
9222                 t->currentskinframe = r_qwskincache[i].skinframe;
9223                 if (t->currentskinframe == NULL)
9224                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9225         }
9226         else if (t->numskinframes >= 2)
9227                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9228         if (t->backgroundnumskinframes >= 2)
9229                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
9230
9231         t->currentmaterialflags = t->basematerialflags;
9232         t->currentalpha = rsurface.colormod[3];
9233         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
9234                 t->currentalpha *= r_wateralpha.value;
9235         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
9236                 t->currentalpha *= t->r_water_wateralpha;
9237         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
9238                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
9239         if (!(rsurface.ent_flags & RENDER_LIGHT))
9240                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
9241         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
9242         {
9243                 // pick a model lighting mode
9244                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
9245                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
9246                 else
9247                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
9248         }
9249         if (rsurface.ent_flags & RENDER_ADDITIVE)
9250                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9251         else if (t->currentalpha < 1)
9252                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9253         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
9254                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
9255         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
9256                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
9257         if (t->backgroundnumskinframes)
9258                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
9259         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
9260         {
9261                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
9262                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
9263         }
9264         else
9265                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
9266         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
9267                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
9268
9269         // there is no tcmod
9270         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9271         {
9272                 t->currenttexmatrix = r_waterscrollmatrix;
9273                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
9274         }
9275         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
9276         {
9277                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
9278                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
9279         }
9280
9281         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9282                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
9283         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9284                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
9285
9286         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
9287         if (t->currentskinframe->qpixels)
9288                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
9289         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
9290         if (!t->basetexture)
9291                 t->basetexture = r_texture_notexture;
9292         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
9293         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
9294         t->nmaptexture = t->currentskinframe->nmap;
9295         if (!t->nmaptexture)
9296                 t->nmaptexture = r_texture_blanknormalmap;
9297         t->glosstexture = r_texture_black;
9298         t->glowtexture = t->currentskinframe->glow;
9299         t->fogtexture = t->currentskinframe->fog;
9300         t->reflectmasktexture = t->currentskinframe->reflect;
9301         if (t->backgroundnumskinframes)
9302         {
9303                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
9304                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
9305                 t->backgroundglosstexture = r_texture_black;
9306                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
9307                 if (!t->backgroundnmaptexture)
9308                         t->backgroundnmaptexture = r_texture_blanknormalmap;
9309         }
9310         else
9311         {
9312                 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
9313                 t->backgroundnmaptexture = r_texture_blanknormalmap;
9314                 t->backgroundglosstexture = r_texture_black;
9315                 t->backgroundglowtexture = NULL;
9316         }
9317         t->specularpower = r_shadow_glossexponent.value;
9318         // TODO: store reference values for these in the texture?
9319         t->specularscale = 0;
9320         if (r_shadow_gloss.integer > 0)
9321         {
9322                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
9323                 {
9324                         if (r_shadow_glossintensity.value > 0)
9325                         {
9326                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
9327                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
9328                                 t->specularscale = r_shadow_glossintensity.value;
9329                         }
9330                 }
9331                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
9332                 {
9333                         t->glosstexture = r_texture_white;
9334                         t->backgroundglosstexture = r_texture_white;
9335                         t->specularscale = r_shadow_gloss2intensity.value;
9336                         t->specularpower = r_shadow_gloss2exponent.value;
9337                 }
9338         }
9339         t->specularscale *= t->specularscalemod;
9340         t->specularpower *= t->specularpowermod;
9341
9342         // lightmaps mode looks bad with dlights using actual texturing, so turn
9343         // off the colormap and glossmap, but leave the normalmap on as it still
9344         // accurately represents the shading involved
9345         if (gl_lightmaps.integer)
9346         {
9347                 t->basetexture = r_texture_grey128;
9348                 t->pantstexture = r_texture_black;
9349                 t->shirttexture = r_texture_black;
9350                 t->nmaptexture = r_texture_blanknormalmap;
9351                 t->glosstexture = r_texture_black;
9352                 t->glowtexture = NULL;
9353                 t->fogtexture = NULL;
9354                 t->reflectmasktexture = NULL;
9355                 t->backgroundbasetexture = NULL;
9356                 t->backgroundnmaptexture = r_texture_blanknormalmap;
9357                 t->backgroundglosstexture = r_texture_black;
9358                 t->backgroundglowtexture = NULL;
9359                 t->specularscale = 0;
9360                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
9361         }
9362
9363         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
9364         VectorClear(t->dlightcolor);
9365         t->currentnumlayers = 0;
9366         if (t->currentmaterialflags & MATERIALFLAG_WALL)
9367         {
9368                 int blendfunc1, blendfunc2;
9369                 qboolean depthmask;
9370                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
9371                 {
9372                         blendfunc1 = GL_SRC_ALPHA;
9373                         blendfunc2 = GL_ONE;
9374                 }
9375                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
9376                 {
9377                         blendfunc1 = GL_SRC_ALPHA;
9378                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
9379                 }
9380                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9381                 {
9382                         blendfunc1 = t->customblendfunc[0];
9383                         blendfunc2 = t->customblendfunc[1];
9384                 }
9385                 else
9386                 {
9387                         blendfunc1 = GL_ONE;
9388                         blendfunc2 = GL_ZERO;
9389                 }
9390                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
9391                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9392                 {
9393                         // fullbright is not affected by r_refdef.lightmapintensity
9394                         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]);
9395                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9396                                 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]);
9397                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9398                                 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]);
9399                 }
9400                 else
9401                 {
9402                         vec3_t ambientcolor;
9403                         float colorscale;
9404                         // set the color tint used for lights affecting this surface
9405                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
9406                         colorscale = 2;
9407                         // q3bsp has no lightmap updates, so the lightstylevalue that
9408                         // would normally be baked into the lightmap must be
9409                         // applied to the color
9410                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
9411                         if (model->type == mod_brushq3)
9412                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
9413                         colorscale *= r_refdef.lightmapintensity;
9414                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
9415                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
9416                         // basic lit geometry
9417                         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]);
9418                         // add pants/shirt if needed
9419                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9420                                 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]);
9421                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9422                                 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]);
9423                         // now add ambient passes if needed
9424                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
9425                         {
9426                                 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]);
9427                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9428                                         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]);
9429                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9430                                         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]);
9431                         }
9432                 }
9433                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
9434                         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]);
9435                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
9436                 {
9437                         // if this is opaque use alpha blend which will darken the earlier
9438                         // passes cheaply.
9439                         //
9440                         // if this is an alpha blended material, all the earlier passes
9441                         // were darkened by fog already, so we only need to add the fog
9442                         // color ontop through the fog mask texture
9443                         //
9444                         // if this is an additive blended material, all the earlier passes
9445                         // were darkened by fog already, and we should not add fog color
9446                         // (because the background was not darkened, there is no fog color
9447                         // that was lost behind it).
9448                         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]);
9449                 }
9450         }
9451
9452         return t->currentframe;
9453 }
9454
9455 rsurfacestate_t rsurface;
9456
9457 void R_Mesh_ResizeArrays(int newvertices)
9458 {
9459         float *base;
9460         if (rsurface.array_size >= newvertices)
9461                 return;
9462         if (rsurface.array_modelvertex3f)
9463                 Mem_Free(rsurface.array_modelvertex3f);
9464         rsurface.array_size = (newvertices + 1023) & ~1023;
9465         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
9466         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
9467         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
9468         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
9469         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
9470         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
9471         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
9472         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
9473         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
9474         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
9475         rsurface.array_color4f           = base + rsurface.array_size * 27;
9476         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
9477 }
9478
9479 void RSurf_ActiveWorldEntity(void)
9480 {
9481         dp_model_t *model = r_refdef.scene.worldmodel;
9482         //if (rsurface.entity == r_refdef.scene.worldentity)
9483         //      return;
9484         rsurface.entity = r_refdef.scene.worldentity;
9485         rsurface.skeleton = NULL;
9486         rsurface.ent_skinnum = 0;
9487         rsurface.ent_qwskin = -1;
9488         rsurface.ent_shadertime = 0;
9489         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
9490         if (rsurface.array_size < model->surfmesh.num_vertices)
9491                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9492         rsurface.matrix = identitymatrix;
9493         rsurface.inversematrix = identitymatrix;
9494         rsurface.matrixscale = 1;
9495         rsurface.inversematrixscale = 1;
9496         R_EntityMatrix(&identitymatrix);
9497         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
9498         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
9499         rsurface.fograngerecip = r_refdef.fograngerecip;
9500         rsurface.fogheightfade = r_refdef.fogheightfade;
9501         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
9502         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9503         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9504         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9505         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9506         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9507         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9508         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
9509         rsurface.colormod[3] = 1;
9510         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);
9511         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9512         rsurface.frameblend[0].lerp = 1;
9513         rsurface.ent_alttextures = false;
9514         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9515         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9516         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
9517         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9518         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9519         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9520         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9521         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9522         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9523         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9524         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9525         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
9526         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9527         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9528         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
9529         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9530         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9531         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
9532         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9533         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9534         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
9535         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9536         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9537         rsurface.modelelement3i = model->surfmesh.data_element3i;
9538         rsurface.modelelement3s = model->surfmesh.data_element3s;
9539         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9540         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9541         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9542         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9543         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9544         rsurface.modelsurfaces = model->data_surfaces;
9545         rsurface.generatedvertex = false;
9546         rsurface.vertex3f  = rsurface.modelvertex3f;
9547         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9548         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9549         rsurface.svector3f = rsurface.modelsvector3f;
9550         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9551         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9552         rsurface.tvector3f = rsurface.modeltvector3f;
9553         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9554         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9555         rsurface.normal3f  = rsurface.modelnormal3f;
9556         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9557         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9558         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9559 }
9560
9561 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
9562 {
9563         dp_model_t *model = ent->model;
9564         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
9565         //      return;
9566         rsurface.entity = (entity_render_t *)ent;
9567         rsurface.skeleton = ent->skeleton;
9568         rsurface.ent_skinnum = ent->skinnum;
9569         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;
9570         rsurface.ent_shadertime = ent->shadertime;
9571         rsurface.ent_flags = ent->flags;
9572         if (rsurface.array_size < model->surfmesh.num_vertices)
9573                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9574         rsurface.matrix = ent->matrix;
9575         rsurface.inversematrix = ent->inversematrix;
9576         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9577         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9578         R_EntityMatrix(&rsurface.matrix);
9579         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9580         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9581         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9582         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9583         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9584         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9585         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
9586         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
9587         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
9588         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
9589         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
9590         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
9591         rsurface.colormod[3] = ent->alpha;
9592         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
9593         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
9594         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
9595         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9596         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9597         if (ent->model->brush.submodel && !prepass)
9598         {
9599                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
9600                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
9601         }
9602         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
9603         {
9604                 if (ent->animcache_vertex3f && !r_framedata_failed)
9605                 {
9606                         rsurface.modelvertex3f = ent->animcache_vertex3f;
9607                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
9608                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
9609                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
9610                 }
9611                 else if (wanttangents)
9612                 {
9613                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9614                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9615                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9616                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9617                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
9618                 }
9619                 else if (wantnormals)
9620                 {
9621                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9622                         rsurface.modelsvector3f = NULL;
9623                         rsurface.modeltvector3f = NULL;
9624                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9625                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
9626                 }
9627                 else
9628                 {
9629                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9630                         rsurface.modelsvector3f = NULL;
9631                         rsurface.modeltvector3f = NULL;
9632                         rsurface.modelnormal3f = NULL;
9633                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
9634                 }
9635                 rsurface.modelvertex3f_bufferobject = 0;
9636                 rsurface.modelvertex3f_bufferoffset = 0;
9637                 rsurface.modelsvector3f_bufferobject = 0;
9638                 rsurface.modelsvector3f_bufferoffset = 0;
9639                 rsurface.modeltvector3f_bufferobject = 0;
9640                 rsurface.modeltvector3f_bufferoffset = 0;
9641                 rsurface.modelnormal3f_bufferobject = 0;
9642                 rsurface.modelnormal3f_bufferoffset = 0;
9643                 rsurface.generatedvertex = true;
9644         }
9645         else
9646         {
9647                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
9648                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9649                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9650                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9651                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9652                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9653                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9654                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9655                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9656                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
9657                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9658                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9659                 rsurface.generatedvertex = false;
9660         }
9661         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
9662         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9663         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9664         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
9665         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9666         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9667         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
9668         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9669         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9670         rsurface.modelelement3i = model->surfmesh.data_element3i;
9671         rsurface.modelelement3s = model->surfmesh.data_element3s;
9672         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9673         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9674         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9675         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9676         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9677         rsurface.modelsurfaces = model->data_surfaces;
9678         rsurface.vertex3f  = rsurface.modelvertex3f;
9679         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9680         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9681         rsurface.svector3f = rsurface.modelsvector3f;
9682         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9683         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9684         rsurface.tvector3f = rsurface.modeltvector3f;
9685         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9686         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9687         rsurface.normal3f  = rsurface.modelnormal3f;
9688         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9689         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9690         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9691 }
9692
9693 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)
9694 {
9695         rsurface.entity = r_refdef.scene.worldentity;
9696         rsurface.skeleton = NULL;
9697         rsurface.ent_skinnum = 0;
9698         rsurface.ent_qwskin = -1;
9699         rsurface.ent_shadertime = shadertime;
9700         rsurface.ent_flags = entflags;
9701         rsurface.modelnum_vertices = numvertices;
9702         rsurface.modelnum_triangles = numtriangles;
9703         if (rsurface.array_size < rsurface.modelnum_vertices)
9704                 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
9705         rsurface.matrix = *matrix;
9706         rsurface.inversematrix = *inversematrix;
9707         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9708         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9709         R_EntityMatrix(&rsurface.matrix);
9710         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9711         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9712         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9713         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9714         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9715         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9716         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9717         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9718         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9719         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9720         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9721         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
9722         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);
9723         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9724         rsurface.frameblend[0].lerp = 1;
9725         rsurface.ent_alttextures = false;
9726         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9727         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9728         if (wanttangents)
9729         {
9730                 rsurface.modelvertex3f = vertex3f;
9731                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
9732                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
9733                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9734         }
9735         else if (wantnormals)
9736         {
9737                 rsurface.modelvertex3f = vertex3f;
9738                 rsurface.modelsvector3f = NULL;
9739                 rsurface.modeltvector3f = NULL;
9740                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9741         }
9742         else
9743         {
9744                 rsurface.modelvertex3f = vertex3f;
9745                 rsurface.modelsvector3f = NULL;
9746                 rsurface.modeltvector3f = NULL;
9747                 rsurface.modelnormal3f = NULL;
9748         }
9749         rsurface.modelvertex3f_bufferobject = 0;
9750         rsurface.modelvertex3f_bufferoffset = 0;
9751         rsurface.modelsvector3f_bufferobject = 0;
9752         rsurface.modelsvector3f_bufferoffset = 0;
9753         rsurface.modeltvector3f_bufferobject = 0;
9754         rsurface.modeltvector3f_bufferoffset = 0;
9755         rsurface.modelnormal3f_bufferobject = 0;
9756         rsurface.modelnormal3f_bufferoffset = 0;
9757         rsurface.generatedvertex = true;
9758         rsurface.modellightmapcolor4f  = color4f;
9759         rsurface.modellightmapcolor4f_bufferobject = 0;
9760         rsurface.modellightmapcolor4f_bufferoffset = 0;
9761         rsurface.modeltexcoordtexture2f  = texcoord2f;
9762         rsurface.modeltexcoordtexture2f_bufferobject = 0;
9763         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9764         rsurface.modeltexcoordlightmap2f  = NULL;
9765         rsurface.modeltexcoordlightmap2f_bufferobject = 0;
9766         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9767         rsurface.modelelement3i = element3i;
9768         rsurface.modelelement3s = element3s;
9769         rsurface.modelelement3i_bufferobject = 0;
9770         rsurface.modelelement3s_bufferobject = 0;
9771         rsurface.modellightmapoffsets = NULL;
9772         rsurface.modelsurfaces = NULL;
9773         rsurface.vertex3f  = rsurface.modelvertex3f;
9774         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9775         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9776         rsurface.svector3f = rsurface.modelsvector3f;
9777         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9778         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9779         rsurface.tvector3f = rsurface.modeltvector3f;
9780         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9781         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9782         rsurface.normal3f  = rsurface.modelnormal3f;
9783         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9784         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9785         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9786
9787         if (rsurface.modelnum_vertices && rsurface.modelelement3i)
9788         {
9789                 if ((wantnormals || wanttangents) && !normal3f)
9790                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9791                 if (wanttangents && !svector3f)
9792                         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);
9793         }
9794 }
9795
9796 float RSurf_FogPoint(const float *v)
9797 {
9798         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9799         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9800         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9801         float FogHeightFade = r_refdef.fogheightfade;
9802         float fogfrac;
9803         unsigned int fogmasktableindex;
9804         if (r_refdef.fogplaneviewabove)
9805                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9806         else
9807                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9808         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9809         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9810 }
9811
9812 float RSurf_FogVertex(const float *v)
9813 {
9814         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9815         float FogPlaneViewDist = rsurface.fogplaneviewdist;
9816         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9817         float FogHeightFade = rsurface.fogheightfade;
9818         float fogfrac;
9819         unsigned int fogmasktableindex;
9820         if (r_refdef.fogplaneviewabove)
9821                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9822         else
9823                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9824         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9825         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9826 }
9827
9828 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9829 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9830 {
9831         int deformindex;
9832         int texturesurfaceindex;
9833         int i, j;
9834         float amplitude;
9835         float animpos;
9836         float scale;
9837         const float *v1, *in_tc;
9838         float *out_tc;
9839         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9840         float waveparms[4];
9841         q3shaderinfo_deform_t *deform;
9842         // 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
9843         if (rsurface.generatedvertex)
9844         {
9845                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
9846                         generatenormals = true;
9847                 for (i = 0;i < Q3MAXDEFORMS;i++)
9848                 {
9849                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
9850                         {
9851                                 generatetangents = true;
9852                                 generatenormals = true;
9853                         }
9854                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
9855                                 generatenormals = true;
9856                 }
9857                 if (generatenormals && !rsurface.modelnormal3f)
9858                 {
9859                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9860                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
9861                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
9862                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9863                 }
9864                 if (generatetangents && !rsurface.modelsvector3f)
9865                 {
9866                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9867                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
9868                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
9869                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9870                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
9871                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
9872                         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);
9873                 }
9874         }
9875         rsurface.vertex3f  = rsurface.modelvertex3f;
9876         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9877         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9878         rsurface.svector3f = rsurface.modelsvector3f;
9879         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9880         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9881         rsurface.tvector3f = rsurface.modeltvector3f;
9882         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9883         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9884         rsurface.normal3f  = rsurface.modelnormal3f;
9885         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9886         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9887         // if vertices are deformed (sprite flares and things in maps, possibly
9888         // water waves, bulges and other deformations), generate them into
9889         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
9890         // (may be static model data or generated data for an animated model, or
9891         //  the previous deform pass)
9892         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
9893         {
9894                 switch (deform->deform)
9895                 {
9896                 default:
9897                 case Q3DEFORM_PROJECTIONSHADOW:
9898                 case Q3DEFORM_TEXT0:
9899                 case Q3DEFORM_TEXT1:
9900                 case Q3DEFORM_TEXT2:
9901                 case Q3DEFORM_TEXT3:
9902                 case Q3DEFORM_TEXT4:
9903                 case Q3DEFORM_TEXT5:
9904                 case Q3DEFORM_TEXT6:
9905                 case Q3DEFORM_TEXT7:
9906                 case Q3DEFORM_NONE:
9907                         break;
9908                 case Q3DEFORM_AUTOSPRITE:
9909                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9910                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9911                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9912                         VectorNormalize(newforward);
9913                         VectorNormalize(newright);
9914                         VectorNormalize(newup);
9915                         // make deformed versions of only the model vertices used by the specified surfaces
9916                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9917                         {
9918                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9919                                 // a single autosprite surface can contain multiple sprites...
9920                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9921                                 {
9922                                         VectorClear(center);
9923                                         for (i = 0;i < 4;i++)
9924                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9925                                         VectorScale(center, 0.25f, center);
9926                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
9927                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
9928                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
9929                                         for (i = 0;i < 4;i++)
9930                                         {
9931                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
9932                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9933                                         }
9934                                 }
9935                                 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);
9936                                 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);
9937                         }
9938                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9939                         rsurface.vertex3f_bufferobject = 0;
9940                         rsurface.vertex3f_bufferoffset = 0;
9941                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9942                         rsurface.svector3f_bufferobject = 0;
9943                         rsurface.svector3f_bufferoffset = 0;
9944                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9945                         rsurface.tvector3f_bufferobject = 0;
9946                         rsurface.tvector3f_bufferoffset = 0;
9947                         rsurface.normal3f = rsurface.array_deformednormal3f;
9948                         rsurface.normal3f_bufferobject = 0;
9949                         rsurface.normal3f_bufferoffset = 0;
9950                         break;
9951                 case Q3DEFORM_AUTOSPRITE2:
9952                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9953                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9954                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9955                         VectorNormalize(newforward);
9956                         VectorNormalize(newright);
9957                         VectorNormalize(newup);
9958                         // make deformed versions of only the model vertices used by the specified surfaces
9959                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9960                         {
9961                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9962                                 const float *v1, *v2;
9963                                 vec3_t start, end;
9964                                 float f, l;
9965                                 struct
9966                                 {
9967                                         float length2;
9968                                         const float *v1;
9969                                         const float *v2;
9970                                 }
9971                                 shortest[2];
9972                                 memset(shortest, 0, sizeof(shortest));
9973                                 // a single autosprite surface can contain multiple sprites...
9974                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9975                                 {
9976                                         VectorClear(center);
9977                                         for (i = 0;i < 4;i++)
9978                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9979                                         VectorScale(center, 0.25f, center);
9980                                         // find the two shortest edges, then use them to define the
9981                                         // axis vectors for rotating around the central axis
9982                                         for (i = 0;i < 6;i++)
9983                                         {
9984                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
9985                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
9986 #if 0
9987                                                 Debug_PolygonBegin(NULL, 0);
9988                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
9989                                                 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);
9990                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
9991                                                 Debug_PolygonEnd();
9992 #endif
9993                                                 l = VectorDistance2(v1, v2);
9994                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9995                                                 if (v1[2] != v2[2])
9996                                                         l += (1.0f / 1024.0f);
9997                                                 if (shortest[0].length2 > l || i == 0)
9998                                                 {
9999                                                         shortest[1] = shortest[0];
10000                                                         shortest[0].length2 = l;
10001                                                         shortest[0].v1 = v1;
10002                                                         shortest[0].v2 = v2;
10003                                                 }
10004                                                 else if (shortest[1].length2 > l || i == 1)
10005                                                 {
10006                                                         shortest[1].length2 = l;
10007                                                         shortest[1].v1 = v1;
10008                                                         shortest[1].v2 = v2;
10009                                                 }
10010                                         }
10011                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
10012                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
10013 #if 0
10014                                         Debug_PolygonBegin(NULL, 0);
10015                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
10016                                         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);
10017                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
10018                                         Debug_PolygonEnd();
10019 #endif
10020                                         // this calculates the right vector from the shortest edge
10021                                         // and the up vector from the edge midpoints
10022                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
10023                                         VectorNormalize(right);
10024                                         VectorSubtract(end, start, up);
10025                                         VectorNormalize(up);
10026                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
10027                                         VectorSubtract(rsurface.localvieworigin, center, forward);
10028                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
10029                                         VectorNegate(forward, forward);
10030                                         VectorReflect(forward, 0, up, forward);
10031                                         VectorNormalize(forward);
10032                                         CrossProduct(up, forward, newright);
10033                                         VectorNormalize(newright);
10034 #if 0
10035                                         Debug_PolygonBegin(NULL, 0);
10036                                         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);
10037                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
10038                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
10039                                         Debug_PolygonEnd();
10040 #endif
10041 #if 0
10042                                         Debug_PolygonBegin(NULL, 0);
10043                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
10044                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
10045                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
10046                                         Debug_PolygonEnd();
10047 #endif
10048                                         // rotate the quad around the up axis vector, this is made
10049                                         // especially easy by the fact we know the quad is flat,
10050                                         // so we only have to subtract the center position and
10051                                         // measure distance along the right vector, and then
10052                                         // multiply that by the newright vector and add back the
10053                                         // center position
10054                                         // we also need to subtract the old position to undo the
10055                                         // displacement from the center, which we do with a
10056                                         // DotProduct, the subtraction/addition of center is also
10057                                         // optimized into DotProducts here
10058                                         l = DotProduct(right, center);
10059                                         for (i = 0;i < 4;i++)
10060                                         {
10061                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
10062                                                 f = DotProduct(right, v1) - l;
10063                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
10064                                         }
10065                                 }
10066                                 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);
10067                                 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);
10068                         }
10069                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
10070                         rsurface.vertex3f_bufferobject = 0;
10071                         rsurface.vertex3f_bufferoffset = 0;
10072                         rsurface.svector3f = rsurface.array_deformedsvector3f;
10073                         rsurface.svector3f_bufferobject = 0;
10074                         rsurface.svector3f_bufferoffset = 0;
10075                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
10076                         rsurface.tvector3f_bufferobject = 0;
10077                         rsurface.tvector3f_bufferoffset = 0;
10078                         rsurface.normal3f = rsurface.array_deformednormal3f;
10079                         rsurface.normal3f_bufferobject = 0;
10080                         rsurface.normal3f_bufferoffset = 0;
10081                         break;
10082                 case Q3DEFORM_NORMAL:
10083                         // deform the normals to make reflections wavey
10084                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10085                         {
10086                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10087                                 for (j = 0;j < surface->num_vertices;j++)
10088                                 {
10089                                         float vertex[3];
10090                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
10091                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
10092                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
10093                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
10094                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
10095                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
10096                                         VectorNormalize(normal);
10097                                 }
10098                                 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);
10099                         }
10100                         rsurface.svector3f = rsurface.array_deformedsvector3f;
10101                         rsurface.svector3f_bufferobject = 0;
10102                         rsurface.svector3f_bufferoffset = 0;
10103                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
10104                         rsurface.tvector3f_bufferobject = 0;
10105                         rsurface.tvector3f_bufferoffset = 0;
10106                         rsurface.normal3f = rsurface.array_deformednormal3f;
10107                         rsurface.normal3f_bufferobject = 0;
10108                         rsurface.normal3f_bufferoffset = 0;
10109                         break;
10110                 case Q3DEFORM_WAVE:
10111                         // deform vertex array to make wavey water and flags and such
10112                         waveparms[0] = deform->waveparms[0];
10113                         waveparms[1] = deform->waveparms[1];
10114                         waveparms[2] = deform->waveparms[2];
10115                         waveparms[3] = deform->waveparms[3];
10116                         // this is how a divisor of vertex influence on deformation
10117                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10118                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10119                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10120                         {
10121                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10122                                 for (j = 0;j < surface->num_vertices;j++)
10123                                 {
10124                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
10125                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
10126                                         // if the wavefunc depends on time, evaluate it per-vertex
10127                                         if (waveparms[3])
10128                                         {
10129                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
10130                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10131                                         }
10132                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
10133                                 }
10134                         }
10135                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
10136                         rsurface.vertex3f_bufferobject = 0;
10137                         rsurface.vertex3f_bufferoffset = 0;
10138                         break;
10139                 case Q3DEFORM_BULGE:
10140                         // deform vertex array to make the surface have moving bulges
10141                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10142                         {
10143                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10144                                 for (j = 0;j < surface->num_vertices;j++)
10145                                 {
10146                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
10147                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
10148                                 }
10149                         }
10150                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
10151                         rsurface.vertex3f_bufferobject = 0;
10152                         rsurface.vertex3f_bufferoffset = 0;
10153                         break;
10154                 case Q3DEFORM_MOVE:
10155                         // deform vertex array
10156                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10157                         VectorScale(deform->parms, scale, waveparms);
10158                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10159                         {
10160                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10161                                 for (j = 0;j < surface->num_vertices;j++)
10162                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
10163                         }
10164                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
10165                         rsurface.vertex3f_bufferobject = 0;
10166                         rsurface.vertex3f_bufferoffset = 0;
10167                         break;
10168                 }
10169         }
10170         // generate texcoords based on the chosen texcoord source
10171         switch(rsurface.texture->tcgen.tcgen)
10172         {
10173         default:
10174         case Q3TCGEN_TEXTURE:
10175                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
10176                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
10177                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
10178                 break;
10179         case Q3TCGEN_LIGHTMAP:
10180                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
10181                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
10182                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
10183                 break;
10184         case Q3TCGEN_VECTOR:
10185                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10186                 {
10187                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10188                         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)
10189                         {
10190                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
10191                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
10192                         }
10193                 }
10194                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
10195                 rsurface.texcoordtexture2f_bufferobject  = 0;
10196                 rsurface.texcoordtexture2f_bufferoffset  = 0;
10197                 break;
10198         case Q3TCGEN_ENVIRONMENT:
10199                 // make environment reflections using a spheremap
10200                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10201                 {
10202                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10203                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
10204                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
10205                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
10206                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
10207                         {
10208                                 // identical to Q3A's method, but executed in worldspace so
10209                                 // carried models can be shiny too
10210
10211                                 float viewer[3], d, reflected[3], worldreflected[3];
10212
10213                                 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
10214                                 // VectorNormalize(viewer);
10215
10216                                 d = DotProduct(normal, viewer);
10217
10218                                 reflected[0] = normal[0]*2*d - viewer[0];
10219                                 reflected[1] = normal[1]*2*d - viewer[1];
10220                                 reflected[2] = normal[2]*2*d - viewer[2];
10221                                 // note: this is proportinal to viewer, so we can normalize later
10222
10223                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10224                                 VectorNormalize(worldreflected);
10225
10226                                 // note: this sphere map only uses world x and z!
10227                                 // so positive and negative y will LOOK THE SAME.
10228                                 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
10229                                 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
10230                         }
10231                 }
10232                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
10233                 rsurface.texcoordtexture2f_bufferobject  = 0;
10234                 rsurface.texcoordtexture2f_bufferoffset  = 0;
10235                 break;
10236         }
10237         // the only tcmod that needs software vertex processing is turbulent, so
10238         // check for it here and apply the changes if needed
10239         // and we only support that as the first one
10240         // (handling a mixture of turbulent and other tcmods would be problematic
10241         //  without punting it entirely to a software path)
10242         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10243         {
10244                 amplitude = rsurface.texture->tcmods[0].parms[1];
10245                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
10246                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10247                 {
10248                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10249                         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)
10250                         {
10251                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10252                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10253                         }
10254                 }
10255                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
10256                 rsurface.texcoordtexture2f_bufferobject  = 0;
10257                 rsurface.texcoordtexture2f_bufferoffset  = 0;
10258         }
10259         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
10260         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
10261         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
10262         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
10263 }
10264
10265 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10266 {
10267         int i, j;
10268         const msurface_t *surface = texturesurfacelist[0];
10269         const msurface_t *surface2;
10270         int firstvertex;
10271         int endvertex;
10272         int numvertices;
10273         int numtriangles;
10274         // TODO: lock all array ranges before render, rather than on each surface
10275         if (texturenumsurfaces == 1)
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         else if (r_batchmode.integer == 2)
10278         {
10279                 #define MAXBATCHTRIANGLES 65536
10280                 int batchtriangles = 0;
10281                 static int batchelements[MAXBATCHTRIANGLES*3];
10282                 for (i = 0;i < texturenumsurfaces;i = j)
10283                 {
10284                         surface = texturesurfacelist[i];
10285                         j = i + 1;
10286                         if (surface->num_triangles > MAXBATCHTRIANGLES)
10287                         {
10288                                 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);
10289                                 continue;
10290                         }
10291                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
10292                         batchtriangles = surface->num_triangles;
10293                         firstvertex = surface->num_firstvertex;
10294                         endvertex = surface->num_firstvertex + surface->num_vertices;
10295                         for (;j < texturenumsurfaces;j++)
10296                         {
10297                                 surface2 = texturesurfacelist[j];
10298                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
10299                                         break;
10300                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
10301                                 batchtriangles += surface2->num_triangles;
10302                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
10303                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
10304                         }
10305                         surface2 = texturesurfacelist[j-1];
10306                         numvertices = endvertex - firstvertex;
10307                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
10308                 }
10309         }
10310         else if (r_batchmode.integer == 1)
10311         {
10312                 for (i = 0;i < texturenumsurfaces;i = j)
10313                 {
10314                         surface = texturesurfacelist[i];
10315                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10316                                 if (texturesurfacelist[j] != surface2)
10317                                         break;
10318                         surface2 = texturesurfacelist[j-1];
10319                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
10320                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
10321                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10322                 }
10323         }
10324         else
10325         {
10326                 for (i = 0;i < texturenumsurfaces;i++)
10327                 {
10328                         surface = texturesurfacelist[i];
10329                         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);
10330                 }
10331         }
10332 }
10333
10334 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
10335 {
10336         switch(vid.renderpath)
10337         {
10338         case RENDERPATH_CGGL:
10339 #ifdef SUPPORTCG
10340                 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
10341                 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
10342 #endif
10343                 break;
10344         case RENDERPATH_GL20:
10345                 if (r_glsl_permutation->loc_Texture_Lightmap  >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
10346                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
10347                 break;
10348         case RENDERPATH_GL13:
10349         case RENDERPATH_GL11:
10350                 R_Mesh_TexBind(0, surface->lightmaptexture);
10351                 break;
10352         }
10353 }
10354
10355 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
10356 {
10357         // pick the closest matching water plane and bind textures
10358         int planeindex, vertexindex;
10359         float d, bestd;
10360         vec3_t vert;
10361         const float *v;
10362         r_waterstate_waterplane_t *p, *bestp;
10363         bestd = 0;
10364         bestp = NULL;
10365         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
10366         {
10367                 if(p->camera_entity != rsurface.texture->camera_entity)
10368                         continue;
10369                 d = 0;
10370                 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
10371                 {
10372                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10373                         d += fabs(PlaneDiff(vert, &p->plane));
10374                 }
10375                 if (bestd > d || !bestp)
10376                 {
10377                         bestd = d;
10378                         bestp = p;
10379                 }
10380         }
10381         switch(vid.renderpath)
10382         {
10383         case RENDERPATH_CGGL:
10384 #ifdef SUPPORTCG
10385                 if (r_cg_permutation->fp_Texture_Refraction) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR
10386                 else if (r_cg_permutation->fp_Texture_First) CG_BindTexture(r_cg_permutation->fp_Texture_First, bestp ? bestp->texture_camera : r_texture_black);CHECKCGERROR
10387                 if (r_cg_permutation->fp_Texture_Reflection) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR
10388 #endif
10389                 break;
10390         case RENDERPATH_GL20:
10391                 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
10392                 else if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST, bestp ? bestp->texture_camera : r_texture_black);
10393                 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
10394                 break;
10395         case RENDERPATH_GL13:
10396         case RENDERPATH_GL11:
10397                 break;
10398         }
10399 }
10400
10401 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10402 {
10403         int i;
10404         const msurface_t *surface;
10405         if (r_waterstate.renderingscene)
10406                 return;
10407         for (i = 0;i < texturenumsurfaces;i++)
10408         {
10409                 surface = texturesurfacelist[i];
10410                 RSurf_BindLightmapForSurface(surface);
10411                 RSurf_BindReflectionForSurface(surface);
10412                 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);
10413         }
10414 }
10415
10416 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10417 {
10418         int i;
10419         int j;
10420         const msurface_t *surface = texturesurfacelist[0];
10421         const msurface_t *surface2;
10422         int firstvertex;
10423         int endvertex;
10424         int numvertices;
10425         int numtriangles;
10426         if (texturenumsurfaces == 1)
10427         {
10428                 RSurf_BindLightmapForSurface(surface);
10429                 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);
10430         }
10431         else if (r_batchmode.integer == 2)
10432         {
10433                 int batchtriangles = 0;
10434                 static int batchelements[MAXBATCHTRIANGLES*3];
10435                 for (i = 0;i < texturenumsurfaces;i = j)
10436                 {
10437                         surface = texturesurfacelist[i];
10438                         RSurf_BindLightmapForSurface(surface);
10439                         j = i + 1;
10440                         if (surface->num_triangles > MAXBATCHTRIANGLES)
10441                         {
10442                                 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);
10443                                 continue;
10444                         }
10445                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
10446                         batchtriangles = surface->num_triangles;
10447                         firstvertex = surface->num_firstvertex;
10448                         endvertex = surface->num_firstvertex + surface->num_vertices;
10449                         for (;j < texturenumsurfaces;j++)
10450                         {
10451                                 surface2 = texturesurfacelist[j];
10452                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
10453                                         break;
10454                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
10455                                 batchtriangles += surface2->num_triangles;
10456                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
10457                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
10458                         }
10459                         surface2 = texturesurfacelist[j-1];
10460                         numvertices = endvertex - firstvertex;
10461                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
10462                 }
10463         }
10464         else if (r_batchmode.integer == 1)
10465         {
10466 #if 0
10467                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
10468                 for (i = 0;i < texturenumsurfaces;i = j)
10469                 {
10470                         surface = texturesurfacelist[i];
10471                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10472                                 if (texturesurfacelist[j] != surface2)
10473                                         break;
10474                         Con_Printf(" %i", j - i);
10475                 }
10476                 Con_Printf("\n");
10477                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
10478 #endif
10479                 for (i = 0;i < texturenumsurfaces;i = j)
10480                 {
10481                         surface = texturesurfacelist[i];
10482                         RSurf_BindLightmapForSurface(surface);
10483                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10484                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
10485                                         break;
10486 #if 0
10487                         Con_Printf(" %i", j - i);
10488 #endif
10489                         surface2 = texturesurfacelist[j-1];
10490                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
10491                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
10492                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10493                 }
10494 #if 0
10495                 Con_Printf("\n");
10496 #endif
10497         }
10498         else
10499         {
10500                 for (i = 0;i < texturenumsurfaces;i++)
10501                 {
10502                         surface = texturesurfacelist[i];
10503                         RSurf_BindLightmapForSurface(surface);
10504                         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);
10505                 }
10506         }
10507 }
10508
10509 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10510 {
10511         int j;
10512         int texturesurfaceindex;
10513         if (r_showsurfaces.integer == 2)
10514         {
10515                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10516                 {
10517                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10518                         for (j = 0;j < surface->num_triangles;j++)
10519                         {
10520                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
10521                                 GL_Color(f, f, f, 1);
10522                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10523                         }
10524                 }
10525         }
10526         else
10527         {
10528                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10529                 {
10530                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10531                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
10532                         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);
10533                         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);
10534                 }
10535         }
10536 }
10537
10538 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10539 {
10540         int texturesurfaceindex;
10541         int i;
10542         const float *v;
10543         float *c2;
10544         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10545         {
10546                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10547                 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)
10548                 {
10549                         c2[0] = 0.5;
10550                         c2[1] = 0.5;
10551                         c2[2] = 0.5;
10552                         c2[3] = 1;
10553                 }
10554         }
10555         rsurface.lightmapcolor4f = rsurface.array_color4f;
10556         rsurface.lightmapcolor4f_bufferobject = 0;
10557         rsurface.lightmapcolor4f_bufferoffset = 0;
10558 }
10559
10560 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10561 {
10562         int texturesurfaceindex;
10563         int i;
10564         float f;
10565         const float *v;
10566         const float *c;
10567         float *c2;
10568         if (rsurface.lightmapcolor4f)
10569         {
10570                 // generate color arrays for the surfaces in this list
10571                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10572                 {
10573                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10574                         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)
10575                         {
10576                                 f = RSurf_FogVertex(v);
10577                                 c2[0] = c[0] * f;
10578                                 c2[1] = c[1] * f;
10579                                 c2[2] = c[2] * f;
10580                                 c2[3] = c[3];
10581                         }
10582                 }
10583         }
10584         else
10585         {
10586                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10587                 {
10588                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10589                         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)
10590                         {
10591                                 f = RSurf_FogVertex(v);
10592                                 c2[0] = f;
10593                                 c2[1] = f;
10594                                 c2[2] = f;
10595                                 c2[3] = 1;
10596                         }
10597                 }
10598         }
10599         rsurface.lightmapcolor4f = rsurface.array_color4f;
10600         rsurface.lightmapcolor4f_bufferobject = 0;
10601         rsurface.lightmapcolor4f_bufferoffset = 0;
10602 }
10603
10604 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10605 {
10606         int texturesurfaceindex;
10607         int i;
10608         float f;
10609         const float *v;
10610         const float *c;
10611         float *c2;
10612         if (!rsurface.lightmapcolor4f)
10613                 return;
10614         // generate color arrays for the surfaces in this list
10615         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10616         {
10617                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10618                 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)
10619                 {
10620                         f = RSurf_FogVertex(v);
10621                         c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10622                         c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10623                         c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10624                         c2[3] = c[3];
10625                 }
10626         }
10627         rsurface.lightmapcolor4f = rsurface.array_color4f;
10628         rsurface.lightmapcolor4f_bufferobject = 0;
10629         rsurface.lightmapcolor4f_bufferoffset = 0;
10630 }
10631
10632 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
10633 {
10634         int texturesurfaceindex;
10635         int i;
10636         const float *c;
10637         float *c2;
10638         if (!rsurface.lightmapcolor4f)
10639                 return;
10640         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10641         {
10642                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10643                 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)
10644                 {
10645                         c2[0] = c[0] * r;
10646                         c2[1] = c[1] * g;
10647                         c2[2] = c[2] * b;
10648                         c2[3] = c[3] * a;
10649                 }
10650         }
10651         rsurface.lightmapcolor4f = rsurface.array_color4f;
10652         rsurface.lightmapcolor4f_bufferobject = 0;
10653         rsurface.lightmapcolor4f_bufferoffset = 0;
10654 }
10655
10656 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10657 {
10658         int texturesurfaceindex;
10659         int i;
10660         const float *c;
10661         float *c2;
10662         if (!rsurface.lightmapcolor4f)
10663                 return;
10664         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10665         {
10666                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10667                 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)
10668                 {
10669                         c2[0] = c[0] + r_refdef.scene.ambient;
10670                         c2[1] = c[1] + r_refdef.scene.ambient;
10671                         c2[2] = c[2] + r_refdef.scene.ambient;
10672                         c2[3] = c[3];
10673                 }
10674         }
10675         rsurface.lightmapcolor4f = rsurface.array_color4f;
10676         rsurface.lightmapcolor4f_bufferobject = 0;
10677         rsurface.lightmapcolor4f_bufferoffset = 0;
10678 }
10679
10680 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10681 {
10682         // TODO: optimize
10683         rsurface.lightmapcolor4f = NULL;
10684         rsurface.lightmapcolor4f_bufferobject = 0;
10685         rsurface.lightmapcolor4f_bufferoffset = 0;
10686         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10687         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10688         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10689         GL_Color(r, g, b, a);
10690         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10691 }
10692
10693 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10694 {
10695         // TODO: optimize applyfog && applycolor case
10696         // just apply fog if necessary, and tint the fog color array if necessary
10697         rsurface.lightmapcolor4f = NULL;
10698         rsurface.lightmapcolor4f_bufferobject = 0;
10699         rsurface.lightmapcolor4f_bufferoffset = 0;
10700         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10701         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10702         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10703         GL_Color(r, g, b, a);
10704         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10705 }
10706
10707 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10708 {
10709         int texturesurfaceindex;
10710         int i;
10711         float *c;
10712         // TODO: optimize
10713         if (texturesurfacelist[0]->lightmapinfo)
10714         {
10715                 // generate color arrays for the surfaces in this list
10716                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10717                 {
10718                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10719                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
10720                         {
10721                                 if (surface->lightmapinfo->samples)
10722                                 {
10723                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
10724                                         float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
10725                                         VectorScale(lm, scale, c);
10726                                         if (surface->lightmapinfo->styles[1] != 255)
10727                                         {
10728                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
10729                                                 lm += size3;
10730                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
10731                                                 VectorMA(c, scale, lm, c);
10732                                                 if (surface->lightmapinfo->styles[2] != 255)
10733                                                 {
10734                                                         lm += size3;
10735                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
10736                                                         VectorMA(c, scale, lm, c);
10737                                                         if (surface->lightmapinfo->styles[3] != 255)
10738                                                         {
10739                                                                 lm += size3;
10740                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
10741                                                                 VectorMA(c, scale, lm, c);
10742                                                         }
10743                                                 }
10744                                         }
10745                                 }
10746                                 else
10747                                         VectorClear(c);
10748                                 c[3] = 1;
10749                         }
10750                 }
10751                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10752                 rsurface.lightmapcolor4f_bufferobject = 0;
10753                 rsurface.lightmapcolor4f_bufferoffset = 0;
10754         }
10755         else
10756         {
10757                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10758                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10759                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10760         }
10761         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10762         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10763         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10764         GL_Color(r, g, b, a);
10765         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10766 }
10767
10768 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
10769 {
10770         int texturesurfaceindex;
10771         int i;
10772         float f;
10773         float alpha;
10774         const float *v;
10775         const float *n;
10776         float *c;
10777         vec3_t ambientcolor;
10778         vec3_t diffusecolor;
10779         vec3_t lightdir;
10780         // TODO: optimize
10781         // model lighting
10782         VectorCopy(rsurface.modellight_lightdir, lightdir);
10783         f = 0.5f * r_refdef.lightmapintensity;
10784         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10785         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10786         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10787         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10788         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10789         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10790         alpha = *a;
10791         if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
10792         {
10793                 // generate color arrays for the surfaces in this list
10794                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10795                 {
10796                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10797                         int numverts = surface->num_vertices;
10798                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
10799                         n = rsurface.normal3f + 3 * surface->num_firstvertex;
10800                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
10801                         // q3-style directional shading
10802                         for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
10803                         {
10804                                 if ((f = DotProduct(n, lightdir)) > 0)
10805                                         VectorMA(ambientcolor, f, diffusecolor, c);
10806                                 else
10807                                         VectorCopy(ambientcolor, c);
10808                                 c[3] = alpha;
10809                         }
10810                 }
10811                 *r = 1;
10812                 *g = 1;
10813                 *b = 1;
10814                 *a = 1;
10815                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10816                 rsurface.lightmapcolor4f_bufferobject = 0;
10817                 rsurface.lightmapcolor4f_bufferoffset = 0;
10818                 *applycolor = false;
10819         }
10820         else
10821         {
10822                 *r = ambientcolor[0];
10823                 *g = ambientcolor[1];
10824                 *b = ambientcolor[2];
10825                 rsurface.lightmapcolor4f = NULL;
10826                 rsurface.lightmapcolor4f_bufferobject = 0;
10827                 rsurface.lightmapcolor4f_bufferoffset = 0;
10828         }
10829 }
10830
10831 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10832 {
10833         RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
10834         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10835         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10836         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10837         GL_Color(r, g, b, a);
10838         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10839 }
10840
10841 void RSurf_SetupDepthAndCulling(void)
10842 {
10843         // submodels are biased to avoid z-fighting with world surfaces that they
10844         // may be exactly overlapping (avoids z-fighting artifacts on certain
10845         // doors and things in Quake maps)
10846         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10847         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10848         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10849         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10850 }
10851
10852 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10853 {
10854         // transparent sky would be ridiculous
10855         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10856                 return;
10857         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10858         skyrenderlater = true;
10859         RSurf_SetupDepthAndCulling();
10860         GL_DepthMask(true);
10861         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10862         // skymasking on them, and Quake3 never did sky masking (unlike
10863         // software Quake and software Quake2), so disable the sky masking
10864         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10865         // and skymasking also looks very bad when noclipping outside the
10866         // level, so don't use it then either.
10867         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
10868         {
10869                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10870                 R_Mesh_ColorPointer(NULL, 0, 0);
10871                 R_Mesh_ResetTextureState();
10872                 if (skyrendermasked)
10873                 {
10874                         R_SetupShader_DepthOrShadow();
10875                         // depth-only (masking)
10876                         GL_ColorMask(0,0,0,0);
10877                         // just to make sure that braindead drivers don't draw
10878                         // anything despite that colormask...
10879                         GL_BlendFunc(GL_ZERO, GL_ONE);
10880                 }
10881                 else
10882                 {
10883                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10884                         // fog sky
10885                         GL_BlendFunc(GL_ONE, GL_ZERO);
10886                 }
10887                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10888                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10889                 if (skyrendermasked)
10890                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10891         }
10892         R_Mesh_ResetTextureState();
10893         GL_Color(1, 1, 1, 1);
10894 }
10895
10896 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10897 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10898 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10899 {
10900         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10901                 return;
10902         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10903         if (prepass)
10904         {
10905                 // render screenspace normalmap to texture
10906                 GL_DepthMask(true);
10907                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY);
10908                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10909         }
10910         else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
10911         {
10912                 // render water or distortion background, then blend surface on top
10913                 GL_DepthMask(true);
10914                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
10915                 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10916                 GL_DepthMask(false);
10917                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
10918                 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10919                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10920                 else
10921                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10922         }
10923         else
10924         {
10925                 // render surface normally
10926                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10927                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
10928                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
10929                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10930                 else if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10931                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10932                 else
10933                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10934         }
10935 }
10936
10937 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10938 {
10939         // OpenGL 1.3 path - anything not completely ancient
10940         int texturesurfaceindex;
10941         qboolean applycolor;
10942         qboolean applyfog;
10943         int layerindex;
10944         const texturelayer_t *layer;
10945         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10946
10947         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10948         {
10949                 vec4_t layercolor;
10950                 int layertexrgbscale;
10951                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10952                 {
10953                         if (layerindex == 0)
10954                                 GL_AlphaTest(true);
10955                         else
10956                         {
10957                                 GL_AlphaTest(false);
10958                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10959                         }
10960                 }
10961                 GL_DepthMask(layer->depthmask && writedepth);
10962                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10963                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10964                 {
10965                         layertexrgbscale = 4;
10966                         VectorScale(layer->color, 0.25f, layercolor);
10967                 }
10968                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10969                 {
10970                         layertexrgbscale = 2;
10971                         VectorScale(layer->color, 0.5f, layercolor);
10972                 }
10973                 else
10974                 {
10975                         layertexrgbscale = 1;
10976                         VectorScale(layer->color, 1.0f, layercolor);
10977                 }
10978                 layercolor[3] = layer->color[3];
10979                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10980                 R_Mesh_ColorPointer(NULL, 0, 0);
10981                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10982                 switch (layer->type)
10983                 {
10984                 case TEXTURELAYERTYPE_LITTEXTURE:
10985                         // single-pass lightmapped texture with 2x rgbscale
10986                         R_Mesh_TexBind(0, r_texture_white);
10987                         R_Mesh_TexMatrix(0, NULL);
10988                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10989                         R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10990                         R_Mesh_TexBind(1, layer->texture);
10991                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10992                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10993                         R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10994                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10995                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10996                         else if (rsurface.uselightmaptexture)
10997                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10998                         else
10999                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11000                         break;
11001                 case TEXTURELAYERTYPE_TEXTURE:
11002                         // singletexture unlit texture with transparency support
11003                         R_Mesh_TexBind(0, layer->texture);
11004                         R_Mesh_TexMatrix(0, &layer->texmatrix);
11005                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11006                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11007                         R_Mesh_TexBind(1, 0);
11008                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
11009                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11010                         break;
11011                 case TEXTURELAYERTYPE_FOG:
11012                         // singletexture fogging
11013                         if (layer->texture)
11014                         {
11015                                 R_Mesh_TexBind(0, layer->texture);
11016                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11017                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11018                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11019                         }
11020                         else
11021                         {
11022                                 R_Mesh_TexBind(0, 0);
11023                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
11024                         }
11025                         R_Mesh_TexBind(1, 0);
11026                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
11027                         // generate a color array for the fog pass
11028                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
11029                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11030                         {
11031                                 int i;
11032                                 float f;
11033                                 const float *v;
11034                                 float *c;
11035                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11036                                 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)
11037                                 {
11038                                         f = 1 - RSurf_FogVertex(v);
11039                                         c[0] = layercolor[0];
11040                                         c[1] = layercolor[1];
11041                                         c[2] = layercolor[2];
11042                                         c[3] = f * layercolor[3];
11043                                 }
11044                         }
11045                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11046                         break;
11047                 default:
11048                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11049                 }
11050         }
11051         CHECKGLERROR
11052         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11053         {
11054                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
11055                 GL_AlphaTest(false);
11056         }
11057 }
11058
11059 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11060 {
11061         // OpenGL 1.1 - crusty old voodoo path
11062         int texturesurfaceindex;
11063         qboolean applyfog;
11064         int layerindex;
11065         const texturelayer_t *layer;
11066         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
11067
11068         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
11069         {
11070                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11071                 {
11072                         if (layerindex == 0)
11073                                 GL_AlphaTest(true);
11074                         else
11075                         {
11076                                 GL_AlphaTest(false);
11077                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
11078                         }
11079                 }
11080                 GL_DepthMask(layer->depthmask && writedepth);
11081                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
11082                 R_Mesh_ColorPointer(NULL, 0, 0);
11083                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
11084                 switch (layer->type)
11085                 {
11086                 case TEXTURELAYERTYPE_LITTEXTURE:
11087                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
11088                         {
11089                                 // two-pass lit texture with 2x rgbscale
11090                                 // first the lightmap pass
11091                                 R_Mesh_TexBind(0, r_texture_white);
11092                                 R_Mesh_TexMatrix(0, NULL);
11093                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11094                                 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
11095                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11096                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
11097                                 else if (rsurface.uselightmaptexture)
11098                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
11099                                 else
11100                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
11101                                 // then apply the texture to it
11102                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
11103                                 R_Mesh_TexBind(0, layer->texture);
11104                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11105                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11106                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11107                                 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);
11108                         }
11109                         else
11110                         {
11111                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
11112                                 R_Mesh_TexBind(0, layer->texture);
11113                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11114                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11115                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11116                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11117                                         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);
11118                                 else
11119                                         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);
11120                         }
11121                         break;
11122                 case TEXTURELAYERTYPE_TEXTURE:
11123                         // singletexture unlit texture with transparency support
11124                         R_Mesh_TexBind(0, layer->texture);
11125                         R_Mesh_TexMatrix(0, &layer->texmatrix);
11126                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11127                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11128                         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);
11129                         break;
11130                 case TEXTURELAYERTYPE_FOG:
11131                         // singletexture fogging
11132                         if (layer->texture)
11133                         {
11134                                 R_Mesh_TexBind(0, layer->texture);
11135                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11136                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11137                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11138                         }
11139                         else
11140                         {
11141                                 R_Mesh_TexBind(0, 0);
11142                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
11143                         }
11144                         // generate a color array for the fog pass
11145                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
11146                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11147                         {
11148                                 int i;
11149                                 float f;
11150                                 const float *v;
11151                                 float *c;
11152                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11153                                 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)
11154                                 {
11155                                         f = 1 - RSurf_FogVertex(v);
11156                                         c[0] = layer->color[0];
11157                                         c[1] = layer->color[1];
11158                                         c[2] = layer->color[2];
11159                                         c[3] = f * layer->color[3];
11160                                 }
11161                         }
11162                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11163                         break;
11164                 default:
11165                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11166                 }
11167         }
11168         CHECKGLERROR
11169         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11170         {
11171                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
11172                 GL_AlphaTest(false);
11173         }
11174 }
11175
11176 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11177 {
11178         float c[4];
11179
11180         GL_AlphaTest(false);
11181         R_Mesh_ColorPointer(NULL, 0, 0);
11182         R_Mesh_ResetTextureState();
11183         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11184
11185         if(rsurface.texture && rsurface.texture->currentskinframe)
11186         {
11187                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11188                 c[3] *= rsurface.texture->currentalpha;
11189         }
11190         else
11191         {
11192                 c[0] = 1;
11193                 c[1] = 0;
11194                 c[2] = 1;
11195                 c[3] = 1;
11196         }
11197
11198         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11199         {
11200                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11201                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11202                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11203         }
11204
11205         // brighten it up (as texture value 127 means "unlit")
11206         c[0] *= 2 * r_refdef.view.colorscale;
11207         c[1] *= 2 * r_refdef.view.colorscale;
11208         c[2] *= 2 * r_refdef.view.colorscale;
11209
11210         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11211                 c[3] *= r_wateralpha.value;
11212
11213         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11214         {
11215                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11216                 GL_DepthMask(false);
11217         }
11218         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11219         {
11220                 GL_BlendFunc(GL_ONE, GL_ONE);
11221                 GL_DepthMask(false);
11222         }
11223         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11224         {
11225                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11226                 GL_DepthMask(false);
11227         }
11228         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11229         {
11230                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11231                 GL_DepthMask(false);
11232         }
11233         else
11234         {
11235                 GL_BlendFunc(GL_ONE, GL_ZERO);
11236                 GL_DepthMask(writedepth);
11237         }
11238
11239         rsurface.lightmapcolor4f = NULL;
11240
11241         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11242         {
11243                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11244
11245                 rsurface.lightmapcolor4f = NULL;
11246                 rsurface.lightmapcolor4f_bufferobject = 0;
11247                 rsurface.lightmapcolor4f_bufferoffset = 0;
11248         }
11249         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11250         {
11251                 qboolean applycolor = true;
11252                 float one = 1.0;
11253
11254                 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
11255
11256                 r_refdef.lightmapintensity = 1;
11257                 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
11258                 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11259         }
11260         else
11261         {
11262                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11263
11264                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
11265                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
11266                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11267         }
11268
11269         if(!rsurface.lightmapcolor4f)
11270                 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
11271
11272         RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
11273         RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
11274         if(r_refdef.fogenabled)
11275                 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
11276
11277         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
11278         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11279 }
11280
11281 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11282 {
11283         CHECKGLERROR
11284         RSurf_SetupDepthAndCulling();
11285         if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
11286         {
11287                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
11288                 return;
11289         }
11290         switch (vid.renderpath)
11291         {
11292         case RENDERPATH_GL20:
11293         case RENDERPATH_CGGL:
11294                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11295                 break;
11296         case RENDERPATH_GL13:
11297                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11298                 break;
11299         case RENDERPATH_GL11:
11300                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11301                 break;
11302         }
11303         CHECKGLERROR
11304 }
11305
11306 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11307 {
11308         CHECKGLERROR
11309         RSurf_SetupDepthAndCulling();
11310         if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
11311         {
11312                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
11313                 return;
11314         }
11315         switch (vid.renderpath)
11316         {
11317         case RENDERPATH_GL20:
11318         case RENDERPATH_CGGL:
11319                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11320                 break;
11321         case RENDERPATH_GL13:
11322                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11323                 break;
11324         case RENDERPATH_GL11:
11325                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11326                 break;
11327         }
11328         CHECKGLERROR
11329 }
11330
11331 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11332 {
11333         int i, j;
11334         int texturenumsurfaces, endsurface;
11335         texture_t *texture;
11336         const msurface_t *surface;
11337 #define MAXBATCH_TRANSPARENTSURFACES 256
11338         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
11339
11340         // if the model is static it doesn't matter what value we give for
11341         // wantnormals and wanttangents, so this logic uses only rules applicable
11342         // to a model, knowing that they are meaningless otherwise
11343         if (ent == r_refdef.scene.worldentity)
11344                 RSurf_ActiveWorldEntity();
11345         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11346                 RSurf_ActiveModelEntity(ent, false, false, false);
11347         else
11348         {
11349                 switch (vid.renderpath)
11350                 {
11351                 case RENDERPATH_GL20:
11352                 case RENDERPATH_CGGL:
11353                         RSurf_ActiveModelEntity(ent, true, true, false);
11354                         break;
11355                 case RENDERPATH_GL13:
11356                 case RENDERPATH_GL11:
11357                         RSurf_ActiveModelEntity(ent, true, false, false);
11358                         break;
11359                 }
11360         }
11361
11362         if (r_transparentdepthmasking.integer)
11363         {
11364                 qboolean setup = false;
11365                 for (i = 0;i < numsurfaces;i = j)
11366                 {
11367                         j = i + 1;
11368                         surface = rsurface.modelsurfaces + surfacelist[i];
11369                         texture = surface->texture;
11370                         rsurface.texture = R_GetCurrentTexture(texture);
11371                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11372                         // scan ahead until we find a different texture
11373                         endsurface = min(i + 1024, numsurfaces);
11374                         texturenumsurfaces = 0;
11375                         texturesurfacelist[texturenumsurfaces++] = surface;
11376                         for (;j < endsurface;j++)
11377                         {
11378                                 surface = rsurface.modelsurfaces + surfacelist[j];
11379                                 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
11380                                         break;
11381                                 texturesurfacelist[texturenumsurfaces++] = surface;
11382                         }
11383                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11384                                 continue;
11385                         // render the range of surfaces as depth
11386                         if (!setup)
11387                         {
11388                                 setup = true;
11389                                 GL_ColorMask(0,0,0,0);
11390                                 GL_Color(1,1,1,1);
11391                                 GL_DepthTest(true);
11392                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11393                                 GL_DepthMask(true);
11394                                 GL_AlphaTest(false);
11395                                 R_Mesh_ColorPointer(NULL, 0, 0);
11396                                 R_Mesh_ResetTextureState();
11397                                 R_SetupShader_DepthOrShadow();
11398                         }
11399                         RSurf_SetupDepthAndCulling();
11400                         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11401                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11402                 }
11403                 if (setup)
11404                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11405         }
11406
11407         for (i = 0;i < numsurfaces;i = j)
11408         {
11409                 j = i + 1;
11410                 surface = rsurface.modelsurfaces + surfacelist[i];
11411                 texture = surface->texture;
11412                 rsurface.texture = R_GetCurrentTexture(texture);
11413                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11414                 // scan ahead until we find a different texture
11415                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
11416                 texturenumsurfaces = 0;
11417                 texturesurfacelist[texturenumsurfaces++] = surface;
11418                 for (;j < endsurface;j++)
11419                 {
11420                         surface = rsurface.modelsurfaces + surfacelist[j];
11421                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
11422                                 break;
11423                         texturesurfacelist[texturenumsurfaces++] = surface;
11424                 }
11425                 // render the range of surfaces
11426                 if (ent == r_refdef.scene.worldentity)
11427                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11428                 else
11429                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11430         }
11431         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11432         GL_AlphaTest(false);
11433 }
11434
11435 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
11436 {
11437         // transparent surfaces get pushed off into the transparent queue
11438         int surfacelistindex;
11439         const msurface_t *surface;
11440         vec3_t tempcenter, center;
11441         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11442         {
11443                 surface = texturesurfacelist[surfacelistindex];
11444                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11445                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11446                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11447                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11448                 if (queueentity->transparent_offset) // transparent offset
11449                 {
11450                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
11451                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
11452                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
11453                 }
11454                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
11455         }
11456 }
11457
11458 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11459 {
11460         const entity_render_t *queueentity = r_refdef.scene.worldentity;
11461         CHECKGLERROR
11462         if (depthonly)
11463         {
11464                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11465                         return;
11466                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11467                         return;
11468                 RSurf_SetupDepthAndCulling();
11469                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11470                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11471         }
11472         else if (prepass)
11473         {
11474                 if (!rsurface.texture->currentnumlayers)
11475                         return;
11476                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11477                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11478                 else
11479                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11480         }
11481         else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
11482         {
11483                 RSurf_SetupDepthAndCulling();
11484                 GL_AlphaTest(false);
11485                 R_Mesh_ColorPointer(NULL, 0, 0);
11486                 R_Mesh_ResetTextureState();
11487                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11488                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11489                 GL_DepthMask(true);
11490                 GL_BlendFunc(GL_ONE, GL_ZERO);
11491                 GL_Color(0, 0, 0, 1);
11492                 GL_DepthTest(writedepth);
11493                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11494         }
11495         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
11496         {
11497                 RSurf_SetupDepthAndCulling();
11498                 GL_AlphaTest(false);
11499                 R_Mesh_ColorPointer(NULL, 0, 0);
11500                 R_Mesh_ResetTextureState();
11501                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11502                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11503                 GL_DepthMask(true);
11504                 GL_BlendFunc(GL_ONE, GL_ZERO);
11505                 GL_DepthTest(true);
11506                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11507         }
11508         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11509                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11510         else if (!rsurface.texture->currentnumlayers)
11511                 return;
11512         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11513         {
11514                 // in the deferred case, transparent surfaces were queued during prepass
11515                 if (!r_shadow_usingdeferredprepass)
11516                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11517         }
11518         else
11519         {
11520                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11521                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11522         }
11523         CHECKGLERROR
11524 }
11525
11526 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11527 {
11528         int i, j;
11529         texture_t *texture;
11530         // break the surface list down into batches by texture and use of lightmapping
11531         for (i = 0;i < numsurfaces;i = j)
11532         {
11533                 j = i + 1;
11534                 // texture is the base texture pointer, rsurface.texture is the
11535                 // current frame/skin the texture is directing us to use (for example
11536                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11537                 // use skin 1 instead)
11538                 texture = surfacelist[i]->texture;
11539                 rsurface.texture = R_GetCurrentTexture(texture);
11540                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11541                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11542                 {
11543                         // if this texture is not the kind we want, skip ahead to the next one
11544                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11545                                 ;
11546                         continue;
11547                 }
11548                 // simply scan ahead until we find a different texture or lightmap state
11549                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11550                         ;
11551                 // render the range of surfaces
11552                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11553         }
11554 }
11555
11556 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
11557 {
11558         CHECKGLERROR
11559         if (depthonly)
11560         {
11561                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11562                         return;
11563                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11564                         return;
11565                 RSurf_SetupDepthAndCulling();
11566                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11567                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11568         }
11569         else if (prepass)
11570         {
11571                 if (!rsurface.texture->currentnumlayers)
11572                         return;
11573                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11574                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11575                 else
11576                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11577         }
11578         else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
11579         {
11580                 RSurf_SetupDepthAndCulling();
11581                 GL_AlphaTest(false);
11582                 R_Mesh_ColorPointer(NULL, 0, 0);
11583                 R_Mesh_ResetTextureState();
11584                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11585                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11586                 GL_DepthMask(true);
11587                 GL_BlendFunc(GL_ONE, GL_ZERO);
11588                 GL_Color(0, 0, 0, 1);
11589                 GL_DepthTest(writedepth);
11590                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11591         }
11592         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11593         {
11594                 RSurf_SetupDepthAndCulling();
11595                 GL_AlphaTest(false);
11596                 R_Mesh_ColorPointer(NULL, 0, 0);
11597                 R_Mesh_ResetTextureState();
11598                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11599                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11600                 GL_DepthMask(true);
11601                 GL_BlendFunc(GL_ONE, GL_ZERO);
11602                 GL_DepthTest(true);
11603                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11604         }
11605         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11606                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11607         else if (!rsurface.texture->currentnumlayers)
11608                 return;
11609         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11610         {
11611                 // in the deferred case, transparent surfaces were queued during prepass
11612                 if (!r_shadow_usingdeferredprepass)
11613                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11614         }
11615         else
11616         {
11617                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11618                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11619         }
11620         CHECKGLERROR
11621 }
11622
11623 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11624 {
11625         int i, j;
11626         texture_t *texture;
11627         // break the surface list down into batches by texture and use of lightmapping
11628         for (i = 0;i < numsurfaces;i = j)
11629         {
11630                 j = i + 1;
11631                 // texture is the base texture pointer, rsurface.texture is the
11632                 // current frame/skin the texture is directing us to use (for example
11633                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11634                 // use skin 1 instead)
11635                 texture = surfacelist[i]->texture;
11636                 rsurface.texture = R_GetCurrentTexture(texture);
11637                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11638                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11639                 {
11640                         // if this texture is not the kind we want, skip ahead to the next one
11641                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11642                                 ;
11643                         continue;
11644                 }
11645                 // simply scan ahead until we find a different texture or lightmap state
11646                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11647                         ;
11648                 // render the range of surfaces
11649                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
11650         }
11651 }
11652
11653 float locboxvertex3f[6*4*3] =
11654 {
11655         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11656         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11657         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11658         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11659         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11660         1,0,0, 0,0,0, 0,1,0, 1,1,0
11661 };
11662
11663 unsigned short locboxelements[6*2*3] =
11664 {
11665          0, 1, 2, 0, 2, 3,
11666          4, 5, 6, 4, 6, 7,
11667          8, 9,10, 8,10,11,
11668         12,13,14, 12,14,15,
11669         16,17,18, 16,18,19,
11670         20,21,22, 20,22,23
11671 };
11672
11673 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11674 {
11675         int i, j;
11676         cl_locnode_t *loc = (cl_locnode_t *)ent;
11677         vec3_t mins, size;
11678         float vertex3f[6*4*3];
11679         CHECKGLERROR
11680         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11681         GL_DepthMask(false);
11682         GL_DepthRange(0, 1);
11683         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11684         GL_DepthTest(true);
11685         GL_CullFace(GL_NONE);
11686         R_EntityMatrix(&identitymatrix);
11687
11688         R_Mesh_VertexPointer(vertex3f, 0, 0);
11689         R_Mesh_ColorPointer(NULL, 0, 0);
11690         R_Mesh_ResetTextureState();
11691         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11692
11693         i = surfacelist[0];
11694         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11695                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11696                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11697                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11698
11699         if (VectorCompare(loc->mins, loc->maxs))
11700         {
11701                 VectorSet(size, 2, 2, 2);
11702                 VectorMA(loc->mins, -0.5f, size, mins);
11703         }
11704         else
11705         {
11706                 VectorCopy(loc->mins, mins);
11707                 VectorSubtract(loc->maxs, loc->mins, size);
11708         }
11709
11710         for (i = 0;i < 6*4*3;)
11711                 for (j = 0;j < 3;j++, i++)
11712                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11713
11714         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
11715 }
11716
11717 void R_DrawLocs(void)
11718 {
11719         int index;
11720         cl_locnode_t *loc, *nearestloc;
11721         vec3_t center;
11722         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11723         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11724         {
11725                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11726                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11727         }
11728 }
11729
11730 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11731 {
11732         if (decalsystem->decals)
11733                 Mem_Free(decalsystem->decals);
11734         memset(decalsystem, 0, sizeof(*decalsystem));
11735 }
11736
11737 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)
11738 {
11739         tridecal_t *decal;
11740         tridecal_t *decals;
11741         int i;
11742
11743         // expand or initialize the system
11744         if (decalsystem->maxdecals <= decalsystem->numdecals)
11745         {
11746                 decalsystem_t old = *decalsystem;
11747                 qboolean useshortelements;
11748                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11749                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11750                 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)));
11751                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11752                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11753                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11754                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11755                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11756                 if (decalsystem->numdecals)
11757                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11758                 if (old.decals)
11759                         Mem_Free(old.decals);
11760                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11761                         decalsystem->element3i[i] = i;
11762                 if (useshortelements)
11763                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11764                                 decalsystem->element3s[i] = i;
11765         }
11766
11767         // grab a decal and search for another free slot for the next one
11768         decals = decalsystem->decals;
11769         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11770         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
11771                 ;
11772         decalsystem->freedecal = i;
11773         if (decalsystem->numdecals <= i)
11774                 decalsystem->numdecals = i + 1;
11775
11776         // initialize the decal
11777         decal->lived = 0;
11778         decal->triangleindex = triangleindex;
11779         decal->surfaceindex = surfaceindex;
11780         decal->decalsequence = decalsequence;
11781         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
11782         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
11783         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
11784         decal->color4ub[0][3] = 255;
11785         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
11786         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
11787         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
11788         decal->color4ub[1][3] = 255;
11789         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
11790         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
11791         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
11792         decal->color4ub[2][3] = 255;
11793         decal->vertex3f[0][0] = v0[0];
11794         decal->vertex3f[0][1] = v0[1];
11795         decal->vertex3f[0][2] = v0[2];
11796         decal->vertex3f[1][0] = v1[0];
11797         decal->vertex3f[1][1] = v1[1];
11798         decal->vertex3f[1][2] = v1[2];
11799         decal->vertex3f[2][0] = v2[0];
11800         decal->vertex3f[2][1] = v2[1];
11801         decal->vertex3f[2][2] = v2[2];
11802         decal->texcoord2f[0][0] = t0[0];
11803         decal->texcoord2f[0][1] = t0[1];
11804         decal->texcoord2f[1][0] = t1[0];
11805         decal->texcoord2f[1][1] = t1[1];
11806         decal->texcoord2f[2][0] = t2[0];
11807         decal->texcoord2f[2][1] = t2[1];
11808 }
11809
11810 extern cvar_t cl_decals_bias;
11811 extern cvar_t cl_decals_models;
11812 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11813 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)
11814 {
11815         matrix4x4_t projection;
11816         decalsystem_t *decalsystem;
11817         qboolean dynamic;
11818         dp_model_t *model;
11819         const float *vertex3f;
11820         const msurface_t *surface;
11821         const msurface_t *surfaces;
11822         const int *surfacelist;
11823         const texture_t *texture;
11824         int numtriangles;
11825         int numsurfacelist;
11826         int surfacelistindex;
11827         int surfaceindex;
11828         int triangleindex;
11829         int cornerindex;
11830         int index;
11831         int numpoints;
11832         const int *e;
11833         float localorigin[3];
11834         float localnormal[3];
11835         float localmins[3];
11836         float localmaxs[3];
11837         float localsize;
11838         float v[9][3];
11839         float tc[9][2];
11840         float c[9][4];
11841         //float normal[3];
11842         float planes[6][4];
11843         float f;
11844         float points[2][9][3];
11845         float angles[3];
11846         float temp[3];
11847
11848         decalsystem = &ent->decalsystem;
11849         model = ent->model;
11850         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11851         {
11852                 R_DecalSystem_Reset(&ent->decalsystem);
11853                 return;
11854         }
11855
11856         if (!model->brush.data_nodes && !cl_decals_models.integer)
11857         {
11858                 if (decalsystem->model)
11859                         R_DecalSystem_Reset(decalsystem);
11860                 return;
11861         }
11862
11863         if (decalsystem->model != model)
11864                 R_DecalSystem_Reset(decalsystem);
11865         decalsystem->model = model;
11866
11867         RSurf_ActiveModelEntity(ent, false, false, false);
11868
11869         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11870         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11871         VectorNormalize(localnormal);
11872         localsize = worldsize*rsurface.inversematrixscale;
11873         localmins[0] = localorigin[0] - localsize;
11874         localmins[1] = localorigin[1] - localsize;
11875         localmins[2] = localorigin[2] - localsize;
11876         localmaxs[0] = localorigin[0] + localsize;
11877         localmaxs[1] = localorigin[1] + localsize;
11878         localmaxs[2] = localorigin[2] + localsize;
11879
11880         //VectorCopy(localnormal, planes[4]);
11881         //VectorVectors(planes[4], planes[2], planes[0]);
11882         AnglesFromVectors(angles, localnormal, NULL, false);
11883         AngleVectors(angles, planes[0], planes[2], planes[4]);
11884         VectorNegate(planes[0], planes[1]);
11885         VectorNegate(planes[2], planes[3]);
11886         VectorNegate(planes[4], planes[5]);
11887         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11888         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11889         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11890         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11891         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11892         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11893
11894 #if 1
11895 // works
11896 {
11897         matrix4x4_t forwardprojection;
11898         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11899         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11900 }
11901 #else
11902 // broken
11903 {
11904         float projectionvector[4][3];
11905         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11906         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11907         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11908         projectionvector[0][0] = planes[0][0] * ilocalsize;
11909         projectionvector[0][1] = planes[1][0] * ilocalsize;
11910         projectionvector[0][2] = planes[2][0] * ilocalsize;
11911         projectionvector[1][0] = planes[0][1] * ilocalsize;
11912         projectionvector[1][1] = planes[1][1] * ilocalsize;
11913         projectionvector[1][2] = planes[2][1] * ilocalsize;
11914         projectionvector[2][0] = planes[0][2] * ilocalsize;
11915         projectionvector[2][1] = planes[1][2] * ilocalsize;
11916         projectionvector[2][2] = planes[2][2] * ilocalsize;
11917         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11918         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11919         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11920         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11921 }
11922 #endif
11923
11924         dynamic = model->surfmesh.isanimated;
11925         vertex3f = rsurface.modelvertex3f;
11926         numsurfacelist = model->nummodelsurfaces;
11927         surfacelist = model->sortedmodelsurfaces;
11928         surfaces = model->data_surfaces;
11929         for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11930         {
11931                 surfaceindex = surfacelist[surfacelistindex];
11932                 surface = surfaces + surfaceindex;
11933                 // check cull box first because it rejects more than any other check
11934                 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11935                         continue;
11936                 // skip transparent surfaces
11937                 texture = surface->texture;
11938                 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11939                         continue;
11940                 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11941                         continue;
11942                 numtriangles = surface->num_triangles;
11943                 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
11944                 {
11945                         for (cornerindex = 0;cornerindex < 3;cornerindex++)
11946                         {
11947                                 index = 3*e[cornerindex];
11948                                 VectorCopy(vertex3f + index, v[cornerindex]);
11949                         }
11950                         // cull backfaces
11951                         //TriangleNormal(v[0], v[1], v[2], normal);
11952                         //if (DotProduct(normal, localnormal) < 0.0f)
11953                         //      continue;
11954                         // clip by each of the box planes formed from the projection matrix
11955                         // if anything survives, we emit the decal
11956                         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]);
11957                         if (numpoints < 3)
11958                                 continue;
11959                         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]);
11960                         if (numpoints < 3)
11961                                 continue;
11962                         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]);
11963                         if (numpoints < 3)
11964                                 continue;
11965                         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]);
11966                         if (numpoints < 3)
11967                                 continue;
11968                         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]);
11969                         if (numpoints < 3)
11970                                 continue;
11971                         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]);
11972                         if (numpoints < 3)
11973                                 continue;
11974                         // some part of the triangle survived, so we have to accept it...
11975                         if (dynamic)
11976                         {
11977                                 // dynamic always uses the original triangle
11978                                 numpoints = 3;
11979                                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11980                                 {
11981                                         index = 3*e[cornerindex];
11982                                         VectorCopy(vertex3f + index, v[cornerindex]);
11983                                 }
11984                         }
11985                         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11986                         {
11987                                 // convert vertex positions to texcoords
11988                                 Matrix4x4_Transform(&projection, v[cornerindex], temp);
11989                                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11990                                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11991                                 // calculate distance fade from the projection origin
11992                                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11993                                 f = bound(0.0f, f, 1.0f);
11994                                 c[cornerindex][0] = r * f;
11995                                 c[cornerindex][1] = g * f;
11996                                 c[cornerindex][2] = b * f;
11997                                 c[cornerindex][3] = 1.0f;
11998                                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11999                         }
12000                         if (dynamic)
12001                                 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);
12002                         else
12003                                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
12004                                         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);
12005                 }
12006         }
12007 }
12008
12009 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
12010 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)
12011 {
12012         int renderentityindex;
12013         float worldmins[3];
12014         float worldmaxs[3];
12015         entity_render_t *ent;
12016
12017         if (!cl_decals_newsystem.integer)
12018                 return;
12019
12020         worldmins[0] = worldorigin[0] - worldsize;
12021         worldmins[1] = worldorigin[1] - worldsize;
12022         worldmins[2] = worldorigin[2] - worldsize;
12023         worldmaxs[0] = worldorigin[0] + worldsize;
12024         worldmaxs[1] = worldorigin[1] + worldsize;
12025         worldmaxs[2] = worldorigin[2] + worldsize;
12026
12027         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12028
12029         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
12030         {
12031                 ent = r_refdef.scene.entities[renderentityindex];
12032                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
12033                         continue;
12034
12035                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12036         }
12037 }
12038
12039 typedef struct r_decalsystem_splatqueue_s
12040 {
12041         vec3_t worldorigin;
12042         vec3_t worldnormal;
12043         float color[4];
12044         float tcrange[4];
12045         float worldsize;
12046         int decalsequence;
12047 }
12048 r_decalsystem_splatqueue_t;
12049
12050 int r_decalsystem_numqueued = 0;
12051 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12052
12053 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)
12054 {
12055         r_decalsystem_splatqueue_t *queue;
12056
12057         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12058                 return;
12059
12060         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12061         VectorCopy(worldorigin, queue->worldorigin);
12062         VectorCopy(worldnormal, queue->worldnormal);
12063         Vector4Set(queue->color, r, g, b, a);
12064         Vector4Set(queue->tcrange, s1, t1, s2, t2);
12065         queue->worldsize = worldsize;
12066         queue->decalsequence = cl.decalsequence++;
12067 }
12068
12069 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12070 {
12071         int i;
12072         r_decalsystem_splatqueue_t *queue;
12073
12074         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12075                 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);
12076         r_decalsystem_numqueued = 0;
12077 }
12078
12079 extern cvar_t cl_decals_max;
12080 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12081 {
12082         int i;
12083         decalsystem_t *decalsystem = &ent->decalsystem;
12084         int numdecals;
12085         int killsequence;
12086         tridecal_t *decal;
12087         float frametime;
12088         float lifetime;
12089
12090         if (!decalsystem->numdecals)
12091                 return;
12092
12093         if (r_showsurfaces.integer)
12094                 return;
12095
12096         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12097         {
12098                 R_DecalSystem_Reset(decalsystem);
12099                 return;
12100         }
12101
12102         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
12103         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12104
12105         if (decalsystem->lastupdatetime)
12106                 frametime = (cl.time - decalsystem->lastupdatetime);
12107         else
12108                 frametime = 0;
12109         decalsystem->lastupdatetime = cl.time;
12110         decal = decalsystem->decals;
12111         numdecals = decalsystem->numdecals;
12112
12113         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12114         {
12115                 if (decal->color4ub[0][3])
12116                 {
12117                         decal->lived += frametime;
12118                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
12119                         {
12120                                 memset(decal, 0, sizeof(*decal));
12121                                 if (decalsystem->freedecal > i)
12122                                         decalsystem->freedecal = i;
12123                         }
12124                 }
12125         }
12126         decal = decalsystem->decals;
12127         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
12128                 numdecals--;
12129
12130         // collapse the array by shuffling the tail decals into the gaps
12131         for (;;)
12132         {
12133                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
12134                         decalsystem->freedecal++;
12135                 if (decalsystem->freedecal == numdecals)
12136                         break;
12137                 decal[decalsystem->freedecal] = decal[--numdecals];
12138         }
12139
12140         decalsystem->numdecals = numdecals;
12141
12142         if (numdecals <= 0)
12143         {
12144                 // if there are no decals left, reset decalsystem
12145                 R_DecalSystem_Reset(decalsystem);
12146         }
12147 }
12148
12149 extern skinframe_t *decalskinframe;
12150 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12151 {
12152         int i;
12153         decalsystem_t *decalsystem = &ent->decalsystem;
12154         int numdecals;
12155         tridecal_t *decal;
12156         float faderate;
12157         float alpha;
12158         float *v3f;
12159         float *c4f;
12160         float *t2f;
12161         const int *e;
12162         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12163         int numtris = 0;
12164
12165         numdecals = decalsystem->numdecals;
12166         if (!numdecals)
12167                 return;
12168
12169         if (r_showsurfaces.integer)
12170                 return;
12171
12172         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12173         {
12174                 R_DecalSystem_Reset(decalsystem);
12175                 return;
12176         }
12177
12178         // if the model is static it doesn't matter what value we give for
12179         // wantnormals and wanttangents, so this logic uses only rules applicable
12180         // to a model, knowing that they are meaningless otherwise
12181         if (ent == r_refdef.scene.worldentity)
12182                 RSurf_ActiveWorldEntity();
12183         else
12184                 RSurf_ActiveModelEntity(ent, false, false, false);
12185
12186         decalsystem->lastupdatetime = cl.time;
12187         decal = decalsystem->decals;
12188
12189         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12190
12191         // update vertex positions for animated models
12192         v3f = decalsystem->vertex3f;
12193         c4f = decalsystem->color4f;
12194         t2f = decalsystem->texcoord2f;
12195         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12196         {
12197                 if (!decal->color4ub[0][3])
12198                         continue;
12199
12200                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12201                         continue;
12202
12203                 // update color values for fading decals
12204                 if (decal->lived >= cl_decals_time.value)
12205                 {
12206                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12207                         alpha *= (1.0f/255.0f);
12208                 }
12209                 else
12210                         alpha = 1.0f/255.0f;
12211
12212                 c4f[ 0] = decal->color4ub[0][0] * alpha;
12213                 c4f[ 1] = decal->color4ub[0][1] * alpha;
12214                 c4f[ 2] = decal->color4ub[0][2] * alpha;
12215                 c4f[ 3] = 1;
12216                 c4f[ 4] = decal->color4ub[1][0] * alpha;
12217                 c4f[ 5] = decal->color4ub[1][1] * alpha;
12218                 c4f[ 6] = decal->color4ub[1][2] * alpha;
12219                 c4f[ 7] = 1;
12220                 c4f[ 8] = decal->color4ub[2][0] * alpha;
12221                 c4f[ 9] = decal->color4ub[2][1] * alpha;
12222                 c4f[10] = decal->color4ub[2][2] * alpha;
12223                 c4f[11] = 1;
12224
12225                 t2f[0] = decal->texcoord2f[0][0];
12226                 t2f[1] = decal->texcoord2f[0][1];
12227                 t2f[2] = decal->texcoord2f[1][0];
12228                 t2f[3] = decal->texcoord2f[1][1];
12229                 t2f[4] = decal->texcoord2f[2][0];
12230                 t2f[5] = decal->texcoord2f[2][1];
12231
12232                 // update vertex positions for animated models
12233                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
12234                 {
12235                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12236                         VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
12237                         VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
12238                         VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
12239                 }
12240                 else
12241                 {
12242                         VectorCopy(decal->vertex3f[0], v3f);
12243                         VectorCopy(decal->vertex3f[1], v3f + 3);
12244                         VectorCopy(decal->vertex3f[2], v3f + 6);
12245                 }
12246
12247                 if (r_refdef.fogenabled)
12248                 {
12249                         alpha = RSurf_FogVertex(v3f);
12250                         VectorScale(c4f, alpha, c4f);
12251                         alpha = RSurf_FogVertex(v3f + 3);
12252                         VectorScale(c4f + 4, alpha, c4f + 4);
12253                         alpha = RSurf_FogVertex(v3f + 6);
12254                         VectorScale(c4f + 8, alpha, c4f + 8);
12255                 }
12256
12257                 v3f += 9;
12258                 c4f += 12;
12259                 t2f += 6;
12260                 numtris++;
12261         }
12262
12263         if (numtris > 0)
12264         {
12265                 r_refdef.stats.drawndecals += numtris;
12266
12267                 // now render the decals all at once
12268                 // (this assumes they all use one particle font texture!)
12269                 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);
12270                 R_Mesh_ResetTextureState();
12271                 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
12272                 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
12273                 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
12274                 GL_DepthMask(false);
12275                 GL_DepthRange(0, 1);
12276                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12277                 GL_DepthTest(true);
12278                 GL_CullFace(GL_NONE);
12279                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12280                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
12281                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
12282         }
12283 }
12284
12285 static void R_DrawModelDecals(void)
12286 {
12287         int i, numdecals;
12288
12289         // fade faster when there are too many decals
12290         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12291         for (i = 0;i < r_refdef.scene.numentities;i++)
12292                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12293
12294         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12295         for (i = 0;i < r_refdef.scene.numentities;i++)
12296                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12297                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12298
12299         R_DecalSystem_ApplySplatEntitiesQueue();
12300
12301         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12302         for (i = 0;i < r_refdef.scene.numentities;i++)
12303                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12304
12305         r_refdef.stats.totaldecals += numdecals;
12306
12307         if (r_showsurfaces.integer)
12308                 return;
12309
12310         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12311
12312         for (i = 0;i < r_refdef.scene.numentities;i++)
12313         {
12314                 if (!r_refdef.viewcache.entityvisible[i])
12315                         continue;
12316                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12317                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12318         }
12319 }
12320
12321 extern cvar_t mod_collision_bih;
12322 void R_DrawDebugModel(void)
12323 {
12324         entity_render_t *ent = rsurface.entity;
12325         int i, j, k, l, flagsmask;
12326         const msurface_t *surface;
12327         dp_model_t *model = ent->model;
12328         vec3_t v;
12329
12330         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12331
12332         R_Mesh_ColorPointer(NULL, 0, 0);
12333         R_Mesh_ResetTextureState();
12334         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12335         GL_DepthRange(0, 1);
12336         GL_DepthTest(!r_showdisabledepthtest.integer);
12337         GL_DepthMask(false);
12338         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12339
12340         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12341         {
12342                 int triangleindex;
12343                 int bihleafindex;
12344                 qboolean cullbox = ent == r_refdef.scene.worldentity;
12345                 const q3mbrush_t *brush;
12346                 const bih_t *bih = &model->collision_bih;
12347                 const bih_leaf_t *bihleaf;
12348                 float vertex3f[3][3];
12349                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12350                 cullbox = false;
12351                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12352                 {
12353                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12354                                 continue;
12355                         switch (bihleaf->type)
12356                         {
12357                         case BIH_BRUSH:
12358                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12359                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12360                                 {
12361                                         R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
12362                                         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);
12363                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
12364                                 }
12365                                 break;
12366                         case BIH_COLLISIONTRIANGLE:
12367                                 triangleindex = bihleaf->itemindex;
12368                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12369                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12370                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12371                                 R_Mesh_VertexPointer(vertex3f[0], 0, 0);
12372                                 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);
12373                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, polygonelement3s, 0, 0);
12374                                 break;
12375                         case BIH_RENDERTRIANGLE:
12376                                 triangleindex = bihleaf->itemindex;
12377                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12378                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12379                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12380                                 R_Mesh_VertexPointer(vertex3f[0], 0, 0);
12381                                 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);
12382                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, polygonelement3s, 0, 0);
12383                                 break;
12384                         }
12385                 }
12386         }
12387
12388         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12389
12390         if (r_showtris.integer || r_shownormals.integer)
12391         {
12392                 if (r_showdisabledepthtest.integer)
12393                 {
12394                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12395                         GL_DepthMask(false);
12396                 }
12397                 else
12398                 {
12399                         GL_BlendFunc(GL_ONE, GL_ZERO);
12400                         GL_DepthMask(true);
12401                 }
12402                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12403                 {
12404                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12405                                 continue;
12406                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12407                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12408                         {
12409                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
12410                                 if (r_showtris.value > 0)
12411                                 {
12412                                         if (!rsurface.texture->currentlayers->depthmask)
12413                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12414                                         else if (ent == r_refdef.scene.worldentity)
12415                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12416                                         else
12417                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12418                                         R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
12419                                         R_Mesh_ColorPointer(NULL, 0, 0);
12420                                         R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
12421                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
12422                                         //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
12423                                         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);
12424                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
12425                                         CHECKGLERROR
12426                                 }
12427                                 if (r_shownormals.value < 0)
12428                                 {
12429                                         qglBegin(GL_LINES);
12430                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12431                                         {
12432                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
12433                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12434                                                 qglVertex3f(v[0], v[1], v[2]);
12435                                                 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
12436                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12437                                                 qglVertex3f(v[0], v[1], v[2]);
12438                                         }
12439                                         qglEnd();
12440                                         CHECKGLERROR
12441                                 }
12442                                 if (r_shownormals.value > 0)
12443                                 {
12444                                         qglBegin(GL_LINES);
12445                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12446                                         {
12447                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
12448                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12449                                                 qglVertex3f(v[0], v[1], v[2]);
12450                                                 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
12451                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12452                                                 qglVertex3f(v[0], v[1], v[2]);
12453                                         }
12454                                         qglEnd();
12455                                         CHECKGLERROR
12456                                         qglBegin(GL_LINES);
12457                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12458                                         {
12459                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
12460                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12461                                                 qglVertex3f(v[0], v[1], v[2]);
12462                                                 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
12463                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12464                                                 qglVertex3f(v[0], v[1], v[2]);
12465                                         }
12466                                         qglEnd();
12467                                         CHECKGLERROR
12468                                         qglBegin(GL_LINES);
12469                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12470                                         {
12471                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
12472                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12473                                                 qglVertex3f(v[0], v[1], v[2]);
12474                                                 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
12475                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12476                                                 qglVertex3f(v[0], v[1], v[2]);
12477                                         }
12478                                         qglEnd();
12479                                         CHECKGLERROR
12480                                 }
12481                         }
12482                 }
12483                 rsurface.texture = NULL;
12484         }
12485 }
12486
12487 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
12488 int r_maxsurfacelist = 0;
12489 const msurface_t **r_surfacelist = NULL;
12490 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12491 {
12492         int i, j, endj, flagsmask;
12493         dp_model_t *model = r_refdef.scene.worldmodel;
12494         msurface_t *surfaces;
12495         unsigned char *update;
12496         int numsurfacelist = 0;
12497         if (model == NULL)
12498                 return;
12499
12500         if (r_maxsurfacelist < model->num_surfaces)
12501         {
12502                 r_maxsurfacelist = model->num_surfaces;
12503                 if (r_surfacelist)
12504                         Mem_Free((msurface_t**)r_surfacelist);
12505                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12506         }
12507
12508         RSurf_ActiveWorldEntity();
12509
12510         surfaces = model->data_surfaces;
12511         update = model->brushq1.lightmapupdateflags;
12512
12513         // update light styles on this submodel
12514         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12515         {
12516                 model_brush_lightstyleinfo_t *style;
12517                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12518                 {
12519                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12520                         {
12521                                 int *list = style->surfacelist;
12522                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12523                                 for (j = 0;j < style->numsurfaces;j++)
12524                                         update[list[j]] = true;
12525                         }
12526                 }
12527         }
12528
12529         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12530
12531         if (debug)
12532         {
12533                 R_DrawDebugModel();
12534                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12535                 return;
12536         }
12537
12538         rsurface.uselightmaptexture = false;
12539         rsurface.texture = NULL;
12540         rsurface.rtlight = NULL;
12541         numsurfacelist = 0;
12542         // add visible surfaces to draw list
12543         for (i = 0;i < model->nummodelsurfaces;i++)
12544         {
12545                 j = model->sortedmodelsurfaces[i];
12546                 if (r_refdef.viewcache.world_surfacevisible[j])
12547                         r_surfacelist[numsurfacelist++] = surfaces + j;
12548         }
12549         // update lightmaps if needed
12550         if (model->brushq1.firstrender)
12551         {
12552                 model->brushq1.firstrender = false;
12553                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12554                         if (update[j])
12555                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12556         }
12557         else if (update)
12558         {
12559                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12560                         if (r_refdef.viewcache.world_surfacevisible[j])
12561                                 if (update[j])
12562                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12563         }
12564         // don't do anything if there were no surfaces
12565         if (!numsurfacelist)
12566         {
12567                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12568                 return;
12569         }
12570         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12571         GL_AlphaTest(false);
12572
12573         // add to stats if desired
12574         if (r_speeds.integer && !skysurfaces && !depthonly)
12575         {
12576                 r_refdef.stats.world_surfaces += numsurfacelist;
12577                 for (j = 0;j < numsurfacelist;j++)
12578                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
12579         }
12580
12581         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12582 }
12583
12584 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12585 {
12586         int i, j, endj, flagsmask;
12587         dp_model_t *model = ent->model;
12588         msurface_t *surfaces;
12589         unsigned char *update;
12590         int numsurfacelist = 0;
12591         if (model == NULL)
12592                 return;
12593
12594         if (r_maxsurfacelist < model->num_surfaces)
12595         {
12596                 r_maxsurfacelist = model->num_surfaces;
12597                 if (r_surfacelist)
12598                         Mem_Free((msurface_t **)r_surfacelist);
12599                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12600         }
12601
12602         // if the model is static it doesn't matter what value we give for
12603         // wantnormals and wanttangents, so this logic uses only rules applicable
12604         // to a model, knowing that they are meaningless otherwise
12605         if (ent == r_refdef.scene.worldentity)
12606                 RSurf_ActiveWorldEntity();
12607         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12608                 RSurf_ActiveModelEntity(ent, false, false, false);
12609         else if (prepass)
12610                 RSurf_ActiveModelEntity(ent, true, true, true);
12611         else if (depthonly)
12612         {
12613                 switch (vid.renderpath)
12614                 {
12615                 case RENDERPATH_GL20:
12616                 case RENDERPATH_CGGL:
12617                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12618                         break;
12619                 case RENDERPATH_GL13:
12620                 case RENDERPATH_GL11:
12621                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12622                         break;
12623                 }
12624         }
12625         else
12626         {
12627                 switch (vid.renderpath)
12628                 {
12629                 case RENDERPATH_GL20:
12630                 case RENDERPATH_CGGL:
12631                         RSurf_ActiveModelEntity(ent, true, true, false);
12632                         break;
12633                 case RENDERPATH_GL13:
12634                 case RENDERPATH_GL11:
12635                         RSurf_ActiveModelEntity(ent, true, false, false);
12636                         break;
12637                 }
12638         }
12639
12640         surfaces = model->data_surfaces;
12641         update = model->brushq1.lightmapupdateflags;
12642
12643         // update light styles
12644         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12645         {
12646                 model_brush_lightstyleinfo_t *style;
12647                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12648                 {
12649                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12650                         {
12651                                 int *list = style->surfacelist;
12652                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12653                                 for (j = 0;j < style->numsurfaces;j++)
12654                                         update[list[j]] = true;
12655                         }
12656                 }
12657         }
12658
12659         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12660
12661         if (debug)
12662         {
12663                 R_DrawDebugModel();
12664                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12665                 return;
12666         }
12667
12668         rsurface.uselightmaptexture = false;
12669         rsurface.texture = NULL;
12670         rsurface.rtlight = NULL;
12671         numsurfacelist = 0;
12672         // add visible surfaces to draw list
12673         for (i = 0;i < model->nummodelsurfaces;i++)
12674                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12675         // don't do anything if there were no surfaces
12676         if (!numsurfacelist)
12677         {
12678                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12679                 return;
12680         }
12681         // update lightmaps if needed
12682         if (update)
12683         {
12684                 int updated = 0;
12685                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12686                 {
12687                         if (update[j])
12688                         {
12689                                 updated++;
12690                                 R_BuildLightMap(ent, surfaces + j);
12691                         }
12692                 }
12693         }
12694         if (update)
12695                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12696                         if (update[j])
12697                                 R_BuildLightMap(ent, surfaces + j);
12698         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12699         GL_AlphaTest(false);
12700
12701         // add to stats if desired
12702         if (r_speeds.integer && !skysurfaces && !depthonly)
12703         {
12704                 r_refdef.stats.entities_surfaces += numsurfacelist;
12705                 for (j = 0;j < numsurfacelist;j++)
12706                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
12707         }
12708
12709         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12710 }
12711
12712 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12713 {
12714         static texture_t texture;
12715         static msurface_t surface;
12716         const msurface_t *surfacelist = &surface;
12717
12718         // fake enough texture and surface state to render this geometry
12719
12720         texture.update_lastrenderframe = -1; // regenerate this texture
12721         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12722         texture.currentskinframe = skinframe;
12723         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12724         texture.offsetmapping = OFFSETMAPPING_OFF;
12725         texture.offsetscale = 1;
12726         texture.specularscalemod = 1;
12727         texture.specularpowermod = 1;
12728
12729         surface.texture = &texture;
12730         surface.num_triangles = numtriangles;
12731         surface.num_firsttriangle = firsttriangle;
12732         surface.num_vertices = numvertices;
12733         surface.num_firstvertex = firstvertex;
12734
12735         // now render it
12736         rsurface.texture = R_GetCurrentTexture(surface.texture);
12737         rsurface.uselightmaptexture = false;
12738         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12739 }
12740
12741 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)
12742 {
12743         static msurface_t surface;
12744         const msurface_t *surfacelist = &surface;
12745
12746         // fake enough texture and surface state to render this geometry
12747
12748         surface.texture = texture;
12749         surface.num_triangles = numtriangles;
12750         surface.num_firsttriangle = firsttriangle;
12751         surface.num_vertices = numvertices;
12752         surface.num_firstvertex = firstvertex;
12753
12754         // now render it
12755         rsurface.texture = R_GetCurrentTexture(surface.texture);
12756         rsurface.uselightmaptexture = false;
12757         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12758 }