]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
uservec2 now combines the possibly-blurred scene and the sobel output
[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 #include "cl_video.h"
30
31 mempool_t *r_main_mempool;
32 rtexturepool_t *r_main_texturepool;
33
34 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
35
36 static qboolean r_loadnormalmap;
37 static qboolean r_loadgloss;
38 qboolean r_loadfog;
39 static qboolean r_loaddds;
40 static qboolean r_savedds;
41
42 //
43 // screen size info
44 //
45 r_refdef_t r_refdef;
46
47 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
48 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
49 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
50 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
51 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)"};
52 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
53 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
54 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
55
56 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
57 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"};
58 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
59 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)"};
60 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
61
62 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"};
63 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
64 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
65 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
66 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
67 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
68 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)"};
69 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
70 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
71 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"};
72 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"};
73 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
74 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"};
75 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"};
76 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"};
77 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
78 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
79 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
80 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
81 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
82 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)"};
83 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)"};
84 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
85 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
86 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
87 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
88 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
89 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
90 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
91 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."};
92 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
93 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
94 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
95 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."};
96 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
97 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
98 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
99 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
100 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"};
101 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"};
102 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
103 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
104 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
105 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
106 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"};
107
108 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
109 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
110 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
111 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
112 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
113 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
114 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
115 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
116
117 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)"};
118 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"};
119
120 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
121 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
122 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
123 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
124 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
125
126 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
127 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
128 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
129
130 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)"};
131 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
132 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
133 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
134 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
135 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)"};
136 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)"};
137 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)"};
138 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)"};
139 //cvar_t r_glsl_postprocess_sobel = {CVAR_SAVE, "r_glsl_postprocess_sobel", "0", "1 = use the sobel operator on the final output (this causes grey-scaling), 2 = combine sobel and blur"};
140
141 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)"};
142 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
143 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"};
144 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
145 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
146
147 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
148 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
149 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
150 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
151
152 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
153 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
154 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
155 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
156 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
157 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
158 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
159
160 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
161 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
162 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
163 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)"};
164
165 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"};
166
167 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"};
168
169 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
170
171 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
172 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"};
173 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
174 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
175 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
176 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
177 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)"};
178
179 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
180
181 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)"};
182
183 extern cvar_t v_glslgamma;
184
185 extern qboolean v_flipped_state;
186
187 static struct r_bloomstate_s
188 {
189         qboolean enabled;
190         qboolean hdr;
191
192         int bloomwidth, bloomheight;
193
194         int screentexturewidth, screentextureheight;
195         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
196
197         int bloomtexturewidth, bloomtextureheight;
198         rtexture_t *texture_bloom;
199
200         // arrays for rendering the screen passes
201         float screentexcoord2f[8];
202         float bloomtexcoord2f[8];
203         float offsettexcoord2f[8];
204
205         r_viewport_t viewport;
206 }
207 r_bloomstate;
208
209 r_waterstate_t r_waterstate;
210
211 /// shadow volume bsp struct with automatically growing nodes buffer
212 svbsp_t r_svbsp;
213
214 rtexture_t *r_texture_blanknormalmap;
215 rtexture_t *r_texture_white;
216 rtexture_t *r_texture_grey128;
217 rtexture_t *r_texture_black;
218 rtexture_t *r_texture_notexture;
219 rtexture_t *r_texture_whitecube;
220 rtexture_t *r_texture_normalizationcube;
221 rtexture_t *r_texture_fogattenuation;
222 rtexture_t *r_texture_fogheighttexture;
223 rtexture_t *r_texture_gammaramps;
224 unsigned int r_texture_gammaramps_serial;
225 //rtexture_t *r_texture_fogintensity;
226 rtexture_t *r_texture_reflectcube;
227
228 // TODO: hash lookups?
229 typedef struct cubemapinfo_s
230 {
231         char basename[64];
232         rtexture_t *texture;
233 }
234 cubemapinfo_t;
235
236 int r_texture_numcubemaps;
237 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
238
239 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
240 unsigned int r_numqueries;
241 unsigned int r_maxqueries;
242
243 typedef struct r_qwskincache_s
244 {
245         char name[MAX_QPATH];
246         skinframe_t *skinframe;
247 }
248 r_qwskincache_t;
249
250 static r_qwskincache_t *r_qwskincache;
251 static int r_qwskincache_size;
252
253 /// vertex coordinates for a quad that covers the screen exactly
254 const float r_screenvertex3f[12] =
255 {
256         0, 0, 0,
257         1, 0, 0,
258         1, 1, 0,
259         0, 1, 0
260 };
261
262 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
263 {
264         int i;
265         for (i = 0;i < verts;i++)
266         {
267                 out[0] = in[0] * r;
268                 out[1] = in[1] * g;
269                 out[2] = in[2] * b;
270                 out[3] = in[3];
271                 in += 4;
272                 out += 4;
273         }
274 }
275
276 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
277 {
278         int i;
279         for (i = 0;i < verts;i++)
280         {
281                 out[0] = r;
282                 out[1] = g;
283                 out[2] = b;
284                 out[3] = a;
285                 out += 4;
286         }
287 }
288
289 // FIXME: move this to client?
290 void FOG_clear(void)
291 {
292         if (gamemode == GAME_NEHAHRA)
293         {
294                 Cvar_Set("gl_fogenable", "0");
295                 Cvar_Set("gl_fogdensity", "0.2");
296                 Cvar_Set("gl_fogred", "0.3");
297                 Cvar_Set("gl_foggreen", "0.3");
298                 Cvar_Set("gl_fogblue", "0.3");
299         }
300         r_refdef.fog_density = 0;
301         r_refdef.fog_red = 0;
302         r_refdef.fog_green = 0;
303         r_refdef.fog_blue = 0;
304         r_refdef.fog_alpha = 1;
305         r_refdef.fog_start = 0;
306         r_refdef.fog_end = 16384;
307         r_refdef.fog_height = 1<<30;
308         r_refdef.fog_fadedepth = 128;
309         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
310 }
311
312 static void R_BuildBlankTextures(void)
313 {
314         unsigned char data[4];
315         data[2] = 128; // normal X
316         data[1] = 128; // normal Y
317         data[0] = 255; // normal Z
318         data[3] = 128; // height
319         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
320         data[0] = 255;
321         data[1] = 255;
322         data[2] = 255;
323         data[3] = 255;
324         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
325         data[0] = 128;
326         data[1] = 128;
327         data[2] = 128;
328         data[3] = 255;
329         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
330         data[0] = 0;
331         data[1] = 0;
332         data[2] = 0;
333         data[3] = 255;
334         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
335 }
336
337 static void R_BuildNoTexture(void)
338 {
339         int x, y;
340         unsigned char pix[16][16][4];
341         // this makes a light grey/dark grey checkerboard texture
342         for (y = 0;y < 16;y++)
343         {
344                 for (x = 0;x < 16;x++)
345                 {
346                         if ((y < 8) ^ (x < 8))
347                         {
348                                 pix[y][x][0] = 128;
349                                 pix[y][x][1] = 128;
350                                 pix[y][x][2] = 128;
351                                 pix[y][x][3] = 255;
352                         }
353                         else
354                         {
355                                 pix[y][x][0] = 64;
356                                 pix[y][x][1] = 64;
357                                 pix[y][x][2] = 64;
358                                 pix[y][x][3] = 255;
359                         }
360                 }
361         }
362         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
363 }
364
365 static void R_BuildWhiteCube(void)
366 {
367         unsigned char data[6*1*1*4];
368         memset(data, 255, sizeof(data));
369         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
370 }
371
372 static void R_BuildNormalizationCube(void)
373 {
374         int x, y, side;
375         vec3_t v;
376         vec_t s, t, intensity;
377 #define NORMSIZE 64
378         unsigned char *data;
379         data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
380         for (side = 0;side < 6;side++)
381         {
382                 for (y = 0;y < NORMSIZE;y++)
383                 {
384                         for (x = 0;x < NORMSIZE;x++)
385                         {
386                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
387                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
388                                 switch(side)
389                                 {
390                                 default:
391                                 case 0:
392                                         v[0] = 1;
393                                         v[1] = -t;
394                                         v[2] = -s;
395                                         break;
396                                 case 1:
397                                         v[0] = -1;
398                                         v[1] = -t;
399                                         v[2] = s;
400                                         break;
401                                 case 2:
402                                         v[0] = s;
403                                         v[1] = 1;
404                                         v[2] = t;
405                                         break;
406                                 case 3:
407                                         v[0] = s;
408                                         v[1] = -1;
409                                         v[2] = -t;
410                                         break;
411                                 case 4:
412                                         v[0] = s;
413                                         v[1] = -t;
414                                         v[2] = 1;
415                                         break;
416                                 case 5:
417                                         v[0] = -s;
418                                         v[1] = -t;
419                                         v[2] = -1;
420                                         break;
421                                 }
422                                 intensity = 127.0f / sqrt(DotProduct(v, v));
423                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
424                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
425                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
426                                 data[((side*64+y)*64+x)*4+3] = 255;
427                         }
428                 }
429         }
430         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
431         Mem_Free(data);
432 }
433
434 static void R_BuildFogTexture(void)
435 {
436         int x, b;
437 #define FOGWIDTH 256
438         unsigned char data1[FOGWIDTH][4];
439         //unsigned char data2[FOGWIDTH][4];
440         double d, r, alpha;
441
442         r_refdef.fogmasktable_start = r_refdef.fog_start;
443         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
444         r_refdef.fogmasktable_range = r_refdef.fogrange;
445         r_refdef.fogmasktable_density = r_refdef.fog_density;
446
447         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
448         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
449         {
450                 d = (x * r - r_refdef.fogmasktable_start);
451                 if(developer_extra.integer)
452                         Con_DPrintf("%f ", d);
453                 d = max(0, d);
454                 if (r_fog_exp2.integer)
455                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
456                 else
457                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
458                 if(developer_extra.integer)
459                         Con_DPrintf(" : %f ", alpha);
460                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
461                 if(developer_extra.integer)
462                         Con_DPrintf(" = %f\n", alpha);
463                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
464         }
465
466         for (x = 0;x < FOGWIDTH;x++)
467         {
468                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
469                 data1[x][0] = b;
470                 data1[x][1] = b;
471                 data1[x][2] = b;
472                 data1[x][3] = 255;
473                 //data2[x][0] = 255 - b;
474                 //data2[x][1] = 255 - b;
475                 //data2[x][2] = 255 - b;
476                 //data2[x][3] = 255;
477         }
478         if (r_texture_fogattenuation)
479         {
480                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
481                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
482         }
483         else
484         {
485                 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);
486                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
487         }
488 }
489
490 static void R_BuildFogHeightTexture(void)
491 {
492         unsigned char *inpixels;
493         int size;
494         int x;
495         int y;
496         int j;
497         float c[4];
498         float f;
499         inpixels = NULL;
500         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
501         if (r_refdef.fogheighttexturename[0])
502                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false);
503         if (!inpixels)
504         {
505                 r_refdef.fog_height_tablesize = 0;
506                 if (r_texture_fogheighttexture)
507                         R_FreeTexture(r_texture_fogheighttexture);
508                 r_texture_fogheighttexture = NULL;
509                 if (r_refdef.fog_height_table2d)
510                         Mem_Free(r_refdef.fog_height_table2d);
511                 r_refdef.fog_height_table2d = NULL;
512                 if (r_refdef.fog_height_table1d)
513                         Mem_Free(r_refdef.fog_height_table1d);
514                 r_refdef.fog_height_table1d = NULL;
515                 return;
516         }
517         size = image_width;
518         r_refdef.fog_height_tablesize = size;
519         r_refdef.fog_height_table1d = Mem_Alloc(r_main_mempool, size * 4);
520         r_refdef.fog_height_table2d = Mem_Alloc(r_main_mempool, size * size * 4);
521         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
522         Mem_Free(inpixels);
523         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
524         // average fog color table accounting for every fog layer between a point
525         // and the camera.  (Note: attenuation is handled separately!)
526         for (y = 0;y < size;y++)
527         {
528                 for (x = 0;x < size;x++)
529                 {
530                         Vector4Clear(c);
531                         f = 0;
532                         if (x < y)
533                         {
534                                 for (j = x;j <= y;j++)
535                                 {
536                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
537                                         f++;
538                                 }
539                         }
540                         else
541                         {
542                                 for (j = x;j >= y;j--)
543                                 {
544                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
545                                         f++;
546                                 }
547                         }
548                         f = 1.0f / f;
549                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
550                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
551                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
552                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
553                 }
554         }
555         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, NULL);
556 }
557
558 //=======================================================================================================================================================
559
560 static const char *builtinshaderstring =
561 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
562 "// written by Forest 'LordHavoc' Hale\n"
563 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
564 "\n"
565 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
566 "# define USEFOG\n"
567 "#endif\n"
568 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
569 "#define USELIGHTMAP\n"
570 "#endif\n"
571 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
572 "#define USEEYEVECTOR\n"
573 "#endif\n"
574 "\n"
575 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
576 "# extension GL_ARB_texture_rectangle : enable\n"
577 "#endif\n"
578 "\n"
579 "#ifdef USESHADOWMAP2D\n"
580 "# ifdef GL_EXT_gpu_shader4\n"
581 "#   extension GL_EXT_gpu_shader4 : enable\n"
582 "# endif\n"
583 "# ifdef GL_ARB_texture_gather\n"
584 "#   extension GL_ARB_texture_gather : enable\n"
585 "# else\n"
586 "#   ifdef GL_AMD_texture_texture4\n"
587 "#     extension GL_AMD_texture_texture4 : enable\n"
588 "#   endif\n"
589 "# endif\n"
590 "#endif\n"
591 "\n"
592 "#ifdef USESHADOWMAPCUBE\n"
593 "# extension GL_EXT_gpu_shader4 : enable\n"
594 "#endif\n"
595 "\n"
596 "//#ifdef USESHADOWSAMPLER\n"
597 "//# extension GL_ARB_shadow : enable\n"
598 "//#endif\n"
599 "\n"
600 "//#ifdef __GLSL_CG_DATA_TYPES\n"
601 "//# define myhalf half\n"
602 "//# define myhalf2 half2\n"
603 "//# define myhalf3 half3\n"
604 "//# define myhalf4 half4\n"
605 "//#else\n"
606 "# define myhalf float\n"
607 "# define myhalf2 vec2\n"
608 "# define myhalf3 vec3\n"
609 "# define myhalf4 vec4\n"
610 "//#endif\n"
611 "\n"
612 "#ifdef VERTEX_SHADER\n"
613 "uniform mat4 ModelViewProjectionMatrix;\n"
614 "#endif\n"
615 "\n"
616 "#ifdef MODE_DEPTH_OR_SHADOW\n"
617 "#ifdef VERTEX_SHADER\n"
618 "void main(void)\n"
619 "{\n"
620 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
621 "}\n"
622 "#endif\n"
623 "#else // !MODE_DEPTH_ORSHADOW\n"
624 "\n"
625 "\n"
626 "\n"
627 "\n"
628 "#ifdef MODE_SHOWDEPTH\n"
629 "#ifdef VERTEX_SHADER\n"
630 "void main(void)\n"
631 "{\n"
632 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
633 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
634 "}\n"
635 "#endif\n"
636 "\n"
637 "#ifdef FRAGMENT_SHADER\n"
638 "void main(void)\n"
639 "{\n"
640 "       gl_FragColor = gl_Color;\n"
641 "}\n"
642 "#endif\n"
643 "#else // !MODE_SHOWDEPTH\n"
644 "\n"
645 "\n"
646 "\n"
647 "\n"
648 "#ifdef MODE_POSTPROCESS\n"
649 "varying vec2 TexCoord1;\n"
650 "varying vec2 TexCoord2;\n"
651 "\n"
652 "#ifdef VERTEX_SHADER\n"
653 "void main(void)\n"
654 "{\n"
655 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
656 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
657 "#ifdef USEBLOOM\n"
658 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
659 "#endif\n"
660 "}\n"
661 "#endif\n"
662 "\n"
663 "#ifdef FRAGMENT_SHADER\n"
664 "uniform sampler2D Texture_First;\n"
665 "#ifdef USEBLOOM\n"
666 "uniform sampler2D Texture_Second;\n"
667 "#endif\n"
668 "#ifdef USEGAMMARAMPS\n"
669 "uniform sampler2D Texture_GammaRamps;\n"
670 "#endif\n"
671 "#ifdef USESATURATION\n"
672 "uniform float Saturation;\n"
673 "#endif\n"
674 "#ifdef USEVIEWTINT\n"
675 "uniform vec4 ViewTintColor;\n"
676 "#endif\n"
677 "//uncomment these if you want to use them:\n"
678 "uniform vec4 UserVec1;\n"
679 "//uniform float UseSobel;\n"
680 "uniform vec4 UserVec2;\n"
681 "// uniform vec4 UserVec3;\n"
682 "// uniform vec4 UserVec4;\n"
683 "// uniform float ClientTime;\n"
684 "uniform vec2 PixelSize;\n"
685 "void main(void)\n"
686 "{\n"
687 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
688 "#ifdef USEBLOOM\n"
689 "       gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
690 "#endif\n"
691 "#ifdef USEVIEWTINT\n"
692 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
693 "#endif\n"
694 "\n"
695 "#ifdef USEPOSTPROCESSING\n"
696 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
697 "// 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"
698 "       vec3 sobel = vec3(1.0);\n"
699 "       // vec2 ts = textureSize(Texture_First, 0);\n"
700 "       // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
701 "       vec2 px = PixelSize;\n"
702 "       vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
703 "       vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,  0.0)).rgb;\n"
704 "       vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
705 "       vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
706 "       vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x,  0.0)).rgb;\n"
707 "       vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
708 "       vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
709 "       vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2(  0.0,-px.y)).rgb;\n"
710 "       vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
711 "       vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
712 "       vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2(  0.0, px.y)).rgb;\n"
713 "       vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
714 "       float px1 = -1.0 * (0.30*x1.r + 0.59*x1.g + 0.11*x1.b);\n"
715 "       float px2 = -2.0 * (0.30*x2.r + 0.59*x2.g + 0.11*x2.b);\n"
716 "       float px3 = -1.0 * (0.30*x3.r + 0.59*x3.g + 0.11*x3.b);\n"
717 "       float px4 =  1.0 * (0.30*x4.r + 0.59*x4.g + 0.11*x4.b);\n"
718 "       float px5 =  2.0 * (0.30*x5.r + 0.59*x5.g + 0.11*x5.b);\n"
719 "       float px6 =  1.0 * (0.30*x6.r + 0.59*x6.g + 0.11*x6.b);\n"
720 "       float py1 = -1.0 * (0.30*y1.r + 0.59*y1.g + 0.11*y1.b);\n"
721 "       float py2 = -2.0 * (0.30*y2.r + 0.59*y2.g + 0.11*y2.b);\n"
722 "       float py3 = -1.0 * (0.30*y3.r + 0.59*y3.g + 0.11*y3.b);\n"
723 "       float py4 =  1.0 * (0.30*y4.r + 0.59*y4.g + 0.11*y4.b);\n"
724 "       float py5 =  2.0 * (0.30*y5.r + 0.59*y5.g + 0.11*y5.b);\n"
725 "       float py6 =  1.0 * (0.30*y6.r + 0.59*y6.g + 0.11*y6.b);\n"
726 "       sobel = vec3(0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6));\n"
727 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
728 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
729 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
730 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
731 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
732 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
733 "       //gl_FragColor = mix(gl_FragColor, vec4(vec3(sobel), 1), UseSobel);\n"
734 "       gl_FragColor.rgb = gl_FragColor.rgb * UserVec2.y + vec3(sobel)*UserVec2.x;\n"
735 "#endif\n"
736 "\n"
737 "#ifdef USESATURATION\n"
738 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
739 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
740 "       //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
741 "       gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
742 "#endif\n"
743 "\n"
744 "#ifdef USEGAMMARAMPS\n"
745 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
746 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
747 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
748 "#endif\n"
749 "}\n"
750 "#endif\n"
751 "#else // !MODE_POSTPROCESS\n"
752 "\n"
753 "\n"
754 "\n"
755 "\n"
756 "#ifdef MODE_GENERIC\n"
757 "#ifdef USEDIFFUSE\n"
758 "varying vec2 TexCoord1;\n"
759 "#endif\n"
760 "#ifdef USESPECULAR\n"
761 "varying vec2 TexCoord2;\n"
762 "#endif\n"
763 "#ifdef VERTEX_SHADER\n"
764 "void main(void)\n"
765 "{\n"
766 "       gl_FrontColor = gl_Color;\n"
767 "#ifdef USEDIFFUSE\n"
768 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
769 "#endif\n"
770 "#ifdef USESPECULAR\n"
771 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
772 "#endif\n"
773 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
774 "}\n"
775 "#endif\n"
776 "\n"
777 "#ifdef FRAGMENT_SHADER\n"
778 "#ifdef USEDIFFUSE\n"
779 "uniform sampler2D Texture_First;\n"
780 "#endif\n"
781 "#ifdef USESPECULAR\n"
782 "uniform sampler2D Texture_Second;\n"
783 "#endif\n"
784 "\n"
785 "void main(void)\n"
786 "{\n"
787 "       gl_FragColor = gl_Color;\n"
788 "#ifdef USEDIFFUSE\n"
789 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
790 "#endif\n"
791 "\n"
792 "#ifdef USESPECULAR\n"
793 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
794 "# ifdef USECOLORMAPPING\n"
795 "       gl_FragColor *= tex2;\n"
796 "# endif\n"
797 "# ifdef USEGLOW\n"
798 "       gl_FragColor += tex2;\n"
799 "# endif\n"
800 "# ifdef USEVERTEXTEXTUREBLEND\n"
801 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
802 "# endif\n"
803 "#endif\n"
804 "}\n"
805 "#endif\n"
806 "#else // !MODE_GENERIC\n"
807 "\n"
808 "\n"
809 "\n"
810 "\n"
811 "#ifdef MODE_BLOOMBLUR\n"
812 "varying TexCoord;\n"
813 "#ifdef VERTEX_SHADER\n"
814 "void main(void)\n"
815 "{\n"
816 "       gl_FrontColor = gl_Color;\n"
817 "       TexCoord = gl_MultiTexCoord0.xy;\n"
818 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
819 "}\n"
820 "#endif\n"
821 "\n"
822 "#ifdef FRAGMENT_SHADER\n"
823 "uniform sampler2D Texture_First;\n"
824 "uniform vec4 BloomBlur_Parameters;\n"
825 "\n"
826 "void main(void)\n"
827 "{\n"
828 "       int i;\n"
829 "       vec2 tc = TexCoord;\n"
830 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
831 "       tc += BloomBlur_Parameters.xy;\n"
832 "       for (i = 1;i < SAMPLES;i++)\n"
833 "       {\n"
834 "               color += texture2D(Texture_First, tc).rgb;\n"
835 "               tc += BloomBlur_Parameters.xy;\n"
836 "       }\n"
837 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
838 "}\n"
839 "#endif\n"
840 "#else // !MODE_BLOOMBLUR\n"
841 "#ifdef MODE_REFRACTION\n"
842 "varying vec2 TexCoord;\n"
843 "varying vec4 ModelViewProjectionPosition;\n"
844 "uniform mat4 TexMatrix;\n"
845 "#ifdef VERTEX_SHADER\n"
846 "\n"
847 "void main(void)\n"
848 "{\n"
849 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
850 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
851 "       ModelViewProjectionPosition = gl_Position;\n"
852 "}\n"
853 "#endif\n"
854 "\n"
855 "#ifdef FRAGMENT_SHADER\n"
856 "uniform sampler2D Texture_Normal;\n"
857 "uniform sampler2D Texture_Refraction;\n"
858 "uniform sampler2D Texture_Reflection;\n"
859 "\n"
860 "uniform vec4 DistortScaleRefractReflect;\n"
861 "uniform vec4 ScreenScaleRefractReflect;\n"
862 "uniform vec4 ScreenCenterRefractReflect;\n"
863 "uniform vec4 RefractColor;\n"
864 "uniform vec4 ReflectColor;\n"
865 "uniform float ReflectFactor;\n"
866 "uniform float ReflectOffset;\n"
867 "\n"
868 "void main(void)\n"
869 "{\n"
870 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
871 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
872 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
873 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
874 "       // FIXME temporary hack to detect the case that the reflection\n"
875 "       // gets blackened at edges due to leaving the area that contains actual\n"
876 "       // content.\n"
877 "       // Remove this 'ack once we have a better way to stop this thing from\n"
878 "       // 'appening.\n"
879 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
880 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
881 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
882 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
883 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
884 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
885 "}\n"
886 "#endif\n"
887 "#else // !MODE_REFRACTION\n"
888 "\n"
889 "\n"
890 "\n"
891 "\n"
892 "#ifdef MODE_WATER\n"
893 "varying vec2 TexCoord;\n"
894 "varying vec3 EyeVector;\n"
895 "varying vec4 ModelViewProjectionPosition;\n"
896 "#ifdef VERTEX_SHADER\n"
897 "uniform vec3 EyePosition;\n"
898 "uniform mat4 TexMatrix;\n"
899 "\n"
900 "void main(void)\n"
901 "{\n"
902 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
903 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
904 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
905 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
906 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
907 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
908 "       ModelViewProjectionPosition = gl_Position;\n"
909 "}\n"
910 "#endif\n"
911 "\n"
912 "#ifdef FRAGMENT_SHADER\n"
913 "uniform sampler2D Texture_Normal;\n"
914 "uniform sampler2D Texture_Refraction;\n"
915 "uniform sampler2D Texture_Reflection;\n"
916 "\n"
917 "uniform vec4 DistortScaleRefractReflect;\n"
918 "uniform vec4 ScreenScaleRefractReflect;\n"
919 "uniform vec4 ScreenCenterRefractReflect;\n"
920 "uniform vec4 RefractColor;\n"
921 "uniform vec4 ReflectColor;\n"
922 "uniform float ReflectFactor;\n"
923 "uniform float ReflectOffset;\n"
924 "\n"
925 "void main(void)\n"
926 "{\n"
927 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
928 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
929 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
930 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
931 "       vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
932 "       // FIXME temporary hack to detect the case that the reflection\n"
933 "       // gets blackened at edges due to leaving the area that contains actual\n"
934 "       // content.\n"
935 "       // Remove this 'ack once we have a better way to stop this thing from\n"
936 "       // 'appening.\n"
937 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
938 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
939 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
940 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
941 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
942 "       f       = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
943 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
944 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
945 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
946 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
947 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
948 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
949 "}\n"
950 "#endif\n"
951 "#else // !MODE_WATER\n"
952 "\n"
953 "\n"
954 "\n"
955 "\n"
956 "// common definitions between vertex shader and fragment shader:\n"
957 "\n"
958 "varying vec2 TexCoord;\n"
959 "#ifdef USEVERTEXTEXTUREBLEND\n"
960 "varying vec2 TexCoord2;\n"
961 "#endif\n"
962 "#ifdef USELIGHTMAP\n"
963 "varying vec2 TexCoordLightmap;\n"
964 "#endif\n"
965 "\n"
966 "#ifdef MODE_LIGHTSOURCE\n"
967 "varying vec3 CubeVector;\n"
968 "#endif\n"
969 "\n"
970 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
971 "varying vec3 LightVector;\n"
972 "#endif\n"
973 "\n"
974 "#ifdef USEEYEVECTOR\n"
975 "varying vec3 EyeVector;\n"
976 "#endif\n"
977 "#ifdef USEFOG\n"
978 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
979 "#endif\n"
980 "\n"
981 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
982 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
983 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
984 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
985 "#endif\n"
986 "\n"
987 "#ifdef USEREFLECTION\n"
988 "varying vec4 ModelViewProjectionPosition;\n"
989 "#endif\n"
990 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
991 "uniform vec3 LightPosition;\n"
992 "varying vec4 ModelViewPosition;\n"
993 "#endif\n"
994 "\n"
995 "#ifdef MODE_LIGHTSOURCE\n"
996 "uniform vec3 LightPosition;\n"
997 "#endif\n"
998 "uniform vec3 EyePosition;\n"
999 "#ifdef MODE_LIGHTDIRECTION\n"
1000 "uniform vec3 LightDir;\n"
1001 "#endif\n"
1002 "uniform vec4 FogPlane;\n"
1003 "\n"
1004 "#ifdef USESHADOWMAPORTHO\n"
1005 "varying vec3 ShadowMapTC;\n"
1006 "#endif\n"
1007 "\n"
1008 "\n"
1009 "\n"
1010 "\n"
1011 "\n"
1012 "// 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"
1013 "\n"
1014 "// fragment shader specific:\n"
1015 "#ifdef FRAGMENT_SHADER\n"
1016 "\n"
1017 "uniform sampler2D Texture_Normal;\n"
1018 "uniform sampler2D Texture_Color;\n"
1019 "uniform sampler2D Texture_Gloss;\n"
1020 "#ifdef USEGLOW\n"
1021 "uniform sampler2D Texture_Glow;\n"
1022 "#endif\n"
1023 "#ifdef USEVERTEXTEXTUREBLEND\n"
1024 "uniform sampler2D Texture_SecondaryNormal;\n"
1025 "uniform sampler2D Texture_SecondaryColor;\n"
1026 "uniform sampler2D Texture_SecondaryGloss;\n"
1027 "#ifdef USEGLOW\n"
1028 "uniform sampler2D Texture_SecondaryGlow;\n"
1029 "#endif\n"
1030 "#endif\n"
1031 "#ifdef USECOLORMAPPING\n"
1032 "uniform sampler2D Texture_Pants;\n"
1033 "uniform sampler2D Texture_Shirt;\n"
1034 "#endif\n"
1035 "#ifdef USEFOG\n"
1036 "#ifdef USEFOGHEIGHTTEXTURE\n"
1037 "uniform sampler2D Texture_FogHeightTexture;\n"
1038 "#endif\n"
1039 "uniform sampler2D Texture_FogMask;\n"
1040 "#endif\n"
1041 "#ifdef USELIGHTMAP\n"
1042 "uniform sampler2D Texture_Lightmap;\n"
1043 "#endif\n"
1044 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1045 "uniform sampler2D Texture_Deluxemap;\n"
1046 "#endif\n"
1047 "#ifdef USEREFLECTION\n"
1048 "uniform sampler2D Texture_Reflection;\n"
1049 "#endif\n"
1050 "\n"
1051 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1052 "uniform sampler2D Texture_ScreenDepth;\n"
1053 "uniform sampler2D Texture_ScreenNormalMap;\n"
1054 "#endif\n"
1055 "#ifdef USEDEFERREDLIGHTMAP\n"
1056 "uniform sampler2D Texture_ScreenDiffuse;\n"
1057 "uniform sampler2D Texture_ScreenSpecular;\n"
1058 "#endif\n"
1059 "\n"
1060 "uniform myhalf3 Color_Pants;\n"
1061 "uniform myhalf3 Color_Shirt;\n"
1062 "uniform myhalf3 FogColor;\n"
1063 "\n"
1064 "#ifdef USEFOG\n"
1065 "uniform float FogRangeRecip;\n"
1066 "uniform float FogPlaneViewDist;\n"
1067 "uniform float FogHeightFade;\n"
1068 "vec3 FogVertex(vec3 surfacecolor)\n"
1069 "{\n"
1070 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1071 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1072 "       float fogfrac;\n"
1073 "#ifdef USEFOGHEIGHTTEXTURE\n"
1074 "       vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1075 "       fogfrac = fogheightpixel.a;\n"
1076 "       return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1077 "#else\n"
1078 "# ifdef USEFOGOUTSIDE\n"
1079 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1080 "# else\n"
1081 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1082 "# endif\n"
1083 "       return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1084 "#endif\n"
1085 "}\n"
1086 "#endif\n"
1087 "\n"
1088 "#ifdef USEOFFSETMAPPING\n"
1089 "uniform float OffsetMapping_Scale;\n"
1090 "vec2 OffsetMapping(vec2 TexCoord)\n"
1091 "{\n"
1092 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1093 "       // 14 sample relief mapping: linear search and then binary search\n"
1094 "       // this basically steps forward a small amount repeatedly until it finds\n"
1095 "       // itself inside solid, then jitters forward and back using decreasing\n"
1096 "       // amounts to find the impact\n"
1097 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1098 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1099 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1100 "       vec3 RT = vec3(TexCoord, 1);\n"
1101 "       OffsetVector *= 0.1;\n"
1102 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1103 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1104 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1105 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1106 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1107 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1108 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1109 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1110 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1111 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1112 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1113 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1114 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1115 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1116 "       return RT.xy;\n"
1117 "#else\n"
1118 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1119 "       // this basically moves forward the full distance, and then backs up based\n"
1120 "       // on height of samples\n"
1121 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1122 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1123 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1124 "       TexCoord += OffsetVector;\n"
1125 "       OffsetVector *= 0.333;\n"
1126 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1127 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1128 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1129 "       return TexCoord;\n"
1130 "#endif\n"
1131 "}\n"
1132 "#endif // USEOFFSETMAPPING\n"
1133 "\n"
1134 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1135 "uniform sampler2D Texture_Attenuation;\n"
1136 "uniform samplerCube Texture_Cube;\n"
1137 "#endif\n"
1138 "\n"
1139 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1140 "\n"
1141 "#ifdef USESHADOWMAPRECT\n"
1142 "# ifdef USESHADOWSAMPLER\n"
1143 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1144 "# else\n"
1145 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1146 "# endif\n"
1147 "#endif\n"
1148 "\n"
1149 "#ifdef USESHADOWMAP2D\n"
1150 "# ifdef USESHADOWSAMPLER\n"
1151 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1152 "# else\n"
1153 "uniform sampler2D Texture_ShadowMap2D;\n"
1154 "# endif\n"
1155 "#endif\n"
1156 "\n"
1157 "#ifdef USESHADOWMAPVSDCT\n"
1158 "uniform samplerCube Texture_CubeProjection;\n"
1159 "#endif\n"
1160 "\n"
1161 "#ifdef USESHADOWMAPCUBE\n"
1162 "# ifdef USESHADOWSAMPLER\n"
1163 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1164 "# else\n"
1165 "uniform samplerCube Texture_ShadowMapCube;\n"
1166 "# endif\n"
1167 "#endif\n"
1168 "\n"
1169 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1170 "uniform vec2 ShadowMap_TextureScale;\n"
1171 "uniform vec4 ShadowMap_Parameters;\n"
1172 "#endif\n"
1173 "\n"
1174 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1175 "# ifdef USESHADOWMAPORTHO\n"
1176 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1177 "# else\n"
1178 "#  ifdef USESHADOWMAPVSDCT\n"
1179 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1180 "{\n"
1181 "       vec3 adir = abs(dir);\n"
1182 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1183 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1184 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1185 "}\n"
1186 "#  else\n"
1187 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1188 "{\n"
1189 "       vec3 adir = abs(dir);\n"
1190 "       float ma = adir.z;\n"
1191 "       vec4 proj = vec4(dir, 2.5);\n"
1192 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1193 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1194 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1195 "       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"
1196 "}\n"
1197 "#  endif\n"
1198 "# endif\n"
1199 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1200 "\n"
1201 "#ifdef USESHADOWMAPCUBE\n"
1202 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1203 "{\n"
1204 "       vec3 adir = abs(dir);\n"
1205 "       return vec4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
1206 "}\n"
1207 "#endif\n"
1208 "\n"
1209 "# ifdef USESHADOWMAPRECT\n"
1210 "float ShadowMapCompare(vec3 dir)\n"
1211 "{\n"
1212 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1213 "       float f;\n"
1214 "#  ifdef USESHADOWSAMPLER\n"
1215 "\n"
1216 "#    ifdef USESHADOWMAPPCF\n"
1217 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1218 "       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"
1219 "#    else\n"
1220 "       f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1221 "#    endif\n"
1222 "\n"
1223 "#  else\n"
1224 "\n"
1225 "#    ifdef USESHADOWMAPPCF\n"
1226 "#      if USESHADOWMAPPCF > 1\n"
1227 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1228 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1229 "       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"
1230 "       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"
1231 "       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"
1232 "       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"
1233 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1234 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1235 "#      else\n"
1236 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1237 "       vec2 offset = fract(shadowmaptc.xy);\n"
1238 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1239 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1240 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1241 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1242 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1243 "#      endif\n"
1244 "#    else\n"
1245 "       f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1246 "#    endif\n"
1247 "\n"
1248 "#  endif\n"
1249 "#  ifdef USESHADOWMAPORTHO\n"
1250 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1251 "#  else\n"
1252 "       return f;\n"
1253 "#  endif\n"
1254 "}\n"
1255 "# endif\n"
1256 "\n"
1257 "# ifdef USESHADOWMAP2D\n"
1258 "float ShadowMapCompare(vec3 dir)\n"
1259 "{\n"
1260 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1261 "       float f;\n"
1262 "\n"
1263 "#  ifdef USESHADOWSAMPLER\n"
1264 "#    ifdef USESHADOWMAPPCF\n"
1265 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1266 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1267 "       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"
1268 "#    else\n"
1269 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1270 "#    endif\n"
1271 "#  else\n"
1272 "#    ifdef USESHADOWMAPPCF\n"
1273 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1274 "#      ifdef GL_ARB_texture_gather\n"
1275 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1276 "#      else\n"
1277 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1278 "#      endif\n"
1279 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1280 "#      if USESHADOWMAPPCF > 1\n"
1281 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1282 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1283 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1284 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
1285 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
1286 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
1287 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
1288 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
1289 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
1290 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
1291 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
1292 "       locols.yz += group2.ab;\n"
1293 "       hicols.yz += group8.rg;\n"
1294 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1295 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1296 "                               mix(locols, hicols, offset.y);\n"
1297 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1298 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1299 "       f = dot(cols, vec4(1.0/25.0));\n"
1300 "#      else\n"
1301 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1302 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1303 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1304 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1305 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1306 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1307 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1308 "#      endif\n"
1309 "#     else\n"
1310 "#      ifdef GL_EXT_gpu_shader4\n"
1311 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1312 "#      else\n"
1313 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1314 "#      endif\n"
1315 "#      if USESHADOWMAPPCF > 1\n"
1316 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1317 "       center *= ShadowMap_TextureScale;\n"
1318 "       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"
1319 "       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"
1320 "       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"
1321 "       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"
1322 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1323 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1324 "#      else\n"
1325 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1326 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1327 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1328 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1329 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1330 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1331 "#      endif\n"
1332 "#     endif\n"
1333 "#    else\n"
1334 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1335 "#    endif\n"
1336 "#  endif\n"
1337 "#  ifdef USESHADOWMAPORTHO\n"
1338 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1339 "#  else\n"
1340 "       return f;\n"
1341 "#  endif\n"
1342 "}\n"
1343 "# endif\n"
1344 "\n"
1345 "# ifdef USESHADOWMAPCUBE\n"
1346 "float ShadowMapCompare(vec3 dir)\n"
1347 "{\n"
1348 "       // apply depth texture cubemap as light filter\n"
1349 "       vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1350 "       float f;\n"
1351 "#  ifdef USESHADOWSAMPLER\n"
1352 "       f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1353 "#  else\n"
1354 "       f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1355 "#  endif\n"
1356 "       return f;\n"
1357 "}\n"
1358 "# endif\n"
1359 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1360 "#endif // FRAGMENT_SHADER\n"
1361 "\n"
1362 "\n"
1363 "\n"
1364 "\n"
1365 "#ifdef MODE_DEFERREDGEOMETRY\n"
1366 "#ifdef VERTEX_SHADER\n"
1367 "uniform mat4 TexMatrix;\n"
1368 "#ifdef USEVERTEXTEXTUREBLEND\n"
1369 "uniform mat4 BackgroundTexMatrix;\n"
1370 "#endif\n"
1371 "uniform mat4 ModelViewMatrix;\n"
1372 "void main(void)\n"
1373 "{\n"
1374 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1375 "#ifdef USEVERTEXTEXTUREBLEND\n"
1376 "       gl_FrontColor = gl_Color;\n"
1377 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1378 "#endif\n"
1379 "\n"
1380 "       // transform unnormalized eye direction into tangent space\n"
1381 "#ifdef USEOFFSETMAPPING\n"
1382 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1383 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1384 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1385 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1386 "#endif\n"
1387 "\n"
1388 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1389 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1390 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1391 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1392 "}\n"
1393 "#endif // VERTEX_SHADER\n"
1394 "\n"
1395 "#ifdef FRAGMENT_SHADER\n"
1396 "void main(void)\n"
1397 "{\n"
1398 "#ifdef USEOFFSETMAPPING\n"
1399 "       // apply offsetmapping\n"
1400 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1401 "#define TexCoord TexCoordOffset\n"
1402 "#endif\n"
1403 "\n"
1404 "#ifdef USEALPHAKILL\n"
1405 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1406 "               discard;\n"
1407 "#endif\n"
1408 "\n"
1409 "#ifdef USEVERTEXTEXTUREBLEND\n"
1410 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1411 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1412 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1413 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1414 "#endif\n"
1415 "\n"
1416 "#ifdef USEVERTEXTEXTUREBLEND\n"
1417 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1418 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1419 "#else\n"
1420 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1421 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1422 "#endif\n"
1423 "\n"
1424 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1425 "}\n"
1426 "#endif // FRAGMENT_SHADER\n"
1427 "#else // !MODE_DEFERREDGEOMETRY\n"
1428 "\n"
1429 "\n"
1430 "\n"
1431 "\n"
1432 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1433 "#ifdef VERTEX_SHADER\n"
1434 "uniform mat4 ModelViewMatrix;\n"
1435 "void main(void)\n"
1436 "{\n"
1437 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1438 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1439 "}\n"
1440 "#endif // VERTEX_SHADER\n"
1441 "\n"
1442 "#ifdef FRAGMENT_SHADER\n"
1443 "uniform mat4 ViewToLight;\n"
1444 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1445 "uniform vec2 ScreenToDepth;\n"
1446 "uniform myhalf3 DeferredColor_Ambient;\n"
1447 "uniform myhalf3 DeferredColor_Diffuse;\n"
1448 "#ifdef USESPECULAR\n"
1449 "uniform myhalf3 DeferredColor_Specular;\n"
1450 "uniform myhalf SpecularPower;\n"
1451 "#endif\n"
1452 "uniform myhalf2 PixelToScreenTexCoord;\n"
1453 "void main(void)\n"
1454 "{\n"
1455 "       // calculate viewspace pixel position\n"
1456 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1457 "       vec3 position;\n"
1458 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1459 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1460 "       // decode viewspace pixel normal\n"
1461 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1462 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1463 "       // surfacenormal = pixel normal in viewspace\n"
1464 "       // LightVector = pixel to light in viewspace\n"
1465 "       // CubeVector = position in lightspace\n"
1466 "       // eyevector = pixel to view in viewspace\n"
1467 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1468 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1469 "#ifdef USEDIFFUSE\n"
1470 "       // calculate diffuse shading\n"
1471 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1472 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1473 "#endif\n"
1474 "#ifdef USESPECULAR\n"
1475 "       // calculate directional shading\n"
1476 "       vec3 eyevector = position * -1.0;\n"
1477 "#  ifdef USEEXACTSPECULARMATH\n"
1478 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1479 "#  else\n"
1480 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1481 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1482 "#  endif\n"
1483 "#endif\n"
1484 "\n"
1485 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1486 "       fade *= ShadowMapCompare(CubeVector);\n"
1487 "#endif\n"
1488 "\n"
1489 "#ifdef USEDIFFUSE\n"
1490 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1491 "#else\n"
1492 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1493 "#endif\n"
1494 "#ifdef USESPECULAR\n"
1495 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1496 "#else\n"
1497 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1498 "#endif\n"
1499 "\n"
1500 "# ifdef USECUBEFILTER\n"
1501 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1502 "       gl_FragData[0].rgb *= cubecolor;\n"
1503 "       gl_FragData[1].rgb *= cubecolor;\n"
1504 "# endif\n"
1505 "}\n"
1506 "#endif // FRAGMENT_SHADER\n"
1507 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1508 "\n"
1509 "\n"
1510 "\n"
1511 "\n"
1512 "#ifdef VERTEX_SHADER\n"
1513 "uniform mat4 TexMatrix;\n"
1514 "#ifdef USEVERTEXTEXTUREBLEND\n"
1515 "uniform mat4 BackgroundTexMatrix;\n"
1516 "#endif\n"
1517 "#ifdef MODE_LIGHTSOURCE\n"
1518 "uniform mat4 ModelToLight;\n"
1519 "#endif\n"
1520 "#ifdef USESHADOWMAPORTHO\n"
1521 "uniform mat4 ShadowMapMatrix;\n"
1522 "#endif\n"
1523 "void main(void)\n"
1524 "{\n"
1525 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1526 "       gl_FrontColor = gl_Color;\n"
1527 "#endif\n"
1528 "       // copy the surface texcoord\n"
1529 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1530 "#ifdef USEVERTEXTEXTUREBLEND\n"
1531 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1532 "#endif\n"
1533 "#ifdef USELIGHTMAP\n"
1534 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1535 "#endif\n"
1536 "\n"
1537 "#ifdef MODE_LIGHTSOURCE\n"
1538 "       // transform vertex position into light attenuation/cubemap space\n"
1539 "       // (-1 to +1 across the light box)\n"
1540 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1541 "\n"
1542 "# ifdef USEDIFFUSE\n"
1543 "       // transform unnormalized light direction into tangent space\n"
1544 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1545 "       //  normalize it per pixel)\n"
1546 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1547 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1548 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1549 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1550 "# endif\n"
1551 "#endif\n"
1552 "\n"
1553 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1554 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1555 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1556 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1557 "#endif\n"
1558 "\n"
1559 "       // transform unnormalized eye direction into tangent space\n"
1560 "#ifdef USEEYEVECTOR\n"
1561 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1562 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1563 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1564 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1565 "#endif\n"
1566 "\n"
1567 "#ifdef USEFOG\n"
1568 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1569 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1570 "#endif\n"
1571 "\n"
1572 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1573 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1574 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1575 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1576 "#endif\n"
1577 "\n"
1578 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1579 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1580 "\n"
1581 "#ifdef USESHADOWMAPORTHO\n"
1582 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1583 "#endif\n"
1584 "\n"
1585 "#ifdef USEREFLECTION\n"
1586 "       ModelViewProjectionPosition = gl_Position;\n"
1587 "#endif\n"
1588 "}\n"
1589 "#endif // VERTEX_SHADER\n"
1590 "\n"
1591 "\n"
1592 "\n"
1593 "\n"
1594 "#ifdef FRAGMENT_SHADER\n"
1595 "#ifdef USEDEFERREDLIGHTMAP\n"
1596 "uniform myhalf2 PixelToScreenTexCoord;\n"
1597 "uniform myhalf3 DeferredMod_Diffuse;\n"
1598 "uniform myhalf3 DeferredMod_Specular;\n"
1599 "#endif\n"
1600 "uniform myhalf3 Color_Ambient;\n"
1601 "uniform myhalf3 Color_Diffuse;\n"
1602 "uniform myhalf3 Color_Specular;\n"
1603 "uniform myhalf SpecularPower;\n"
1604 "#ifdef USEGLOW\n"
1605 "uniform myhalf3 Color_Glow;\n"
1606 "#endif\n"
1607 "uniform myhalf Alpha;\n"
1608 "#ifdef USEREFLECTION\n"
1609 "uniform vec4 DistortScaleRefractReflect;\n"
1610 "uniform vec4 ScreenScaleRefractReflect;\n"
1611 "uniform vec4 ScreenCenterRefractReflect;\n"
1612 "uniform myhalf4 ReflectColor;\n"
1613 "#endif\n"
1614 "#ifdef USEREFLECTCUBE\n"
1615 "uniform mat4 ModelToReflectCube;\n"
1616 "uniform sampler2D Texture_ReflectMask;\n"
1617 "uniform samplerCube Texture_ReflectCube;\n"
1618 "#endif\n"
1619 "#ifdef MODE_LIGHTDIRECTION\n"
1620 "uniform myhalf3 LightColor;\n"
1621 "#endif\n"
1622 "#ifdef MODE_LIGHTSOURCE\n"
1623 "uniform myhalf3 LightColor;\n"
1624 "#endif\n"
1625 "void main(void)\n"
1626 "{\n"
1627 "#ifdef USEOFFSETMAPPING\n"
1628 "       // apply offsetmapping\n"
1629 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1630 "#define TexCoord TexCoordOffset\n"
1631 "#endif\n"
1632 "\n"
1633 "       // combine the diffuse textures (base, pants, shirt)\n"
1634 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1635 "#ifdef USEALPHAKILL\n"
1636 "       if (color.a < 0.5)\n"
1637 "               discard;\n"
1638 "#endif\n"
1639 "       color.a *= Alpha;\n"
1640 "#ifdef USECOLORMAPPING\n"
1641 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1642 "#endif\n"
1643 "#ifdef USEVERTEXTEXTUREBLEND\n"
1644 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1645 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1646 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1647 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1648 "       color.a = 1.0;\n"
1649 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1650 "#endif\n"
1651 "\n"
1652 "       // get the surface normal\n"
1653 "#ifdef USEVERTEXTEXTUREBLEND\n"
1654 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1655 "#else\n"
1656 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1657 "#endif\n"
1658 "\n"
1659 "       // get the material colors\n"
1660 "       myhalf3 diffusetex = color.rgb;\n"
1661 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1662 "# ifdef USEVERTEXTEXTUREBLEND\n"
1663 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1664 "# else\n"
1665 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1666 "# endif\n"
1667 "#endif\n"
1668 "\n"
1669 "#ifdef USEREFLECTCUBE\n"
1670 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1671 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1672 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1673 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1674 "#endif\n"
1675 "\n"
1676 "\n"
1677 "\n"
1678 "\n"
1679 "#ifdef MODE_LIGHTSOURCE\n"
1680 "       // light source\n"
1681 "#ifdef USEDIFFUSE\n"
1682 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1683 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1684 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1685 "#ifdef USESPECULAR\n"
1686 "#ifdef USEEXACTSPECULARMATH\n"
1687 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1688 "#else\n"
1689 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1690 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1691 "#endif\n"
1692 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1693 "#endif\n"
1694 "#else\n"
1695 "       color.rgb = diffusetex * Color_Ambient;\n"
1696 "#endif\n"
1697 "       color.rgb *= LightColor;\n"
1698 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1699 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1700 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1701 "#endif\n"
1702 "# ifdef USECUBEFILTER\n"
1703 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1704 "# endif\n"
1705 "#endif // MODE_LIGHTSOURCE\n"
1706 "\n"
1707 "\n"
1708 "\n"
1709 "\n"
1710 "#ifdef MODE_LIGHTDIRECTION\n"
1711 "#define SHADING\n"
1712 "#ifdef USEDIFFUSE\n"
1713 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1714 "#endif\n"
1715 "#define lightcolor LightColor\n"
1716 "#endif // MODE_LIGHTDIRECTION\n"
1717 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1718 "#define SHADING\n"
1719 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1720 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1721 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1722 "       // convert modelspace light vector to tangentspace\n"
1723 "       myhalf3 lightnormal;\n"
1724 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1725 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1726 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1727 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1728 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1729 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1730 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1731 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1732 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1733 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1734 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1735 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1736 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1737 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1738 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1739 "#define SHADING\n"
1740 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1741 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1742 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1743 "#endif\n"
1744 "\n"
1745 "\n"
1746 "\n"
1747 "\n"
1748 "#ifdef MODE_LIGHTMAP\n"
1749 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1750 "#endif // MODE_LIGHTMAP\n"
1751 "#ifdef MODE_VERTEXCOLOR\n"
1752 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1753 "#endif // MODE_VERTEXCOLOR\n"
1754 "#ifdef MODE_FLATCOLOR\n"
1755 "       color.rgb = diffusetex * Color_Ambient;\n"
1756 "#endif // MODE_FLATCOLOR\n"
1757 "\n"
1758 "\n"
1759 "\n"
1760 "\n"
1761 "#ifdef SHADING\n"
1762 "# ifdef USEDIFFUSE\n"
1763 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1764 "#  ifdef USESPECULAR\n"
1765 "#   ifdef USEEXACTSPECULARMATH\n"
1766 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1767 "#   else\n"
1768 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1769 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1770 "#   endif\n"
1771 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1772 "#  else\n"
1773 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1774 "#  endif\n"
1775 "# else\n"
1776 "       color.rgb = diffusetex * Color_Ambient;\n"
1777 "# endif\n"
1778 "#endif\n"
1779 "\n"
1780 "#ifdef USESHADOWMAPORTHO\n"
1781 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1782 "#endif\n"
1783 "\n"
1784 "#ifdef USEDEFERREDLIGHTMAP\n"
1785 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1786 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1787 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1788 "#endif\n"
1789 "\n"
1790 "#ifdef USEGLOW\n"
1791 "#ifdef USEVERTEXTEXTUREBLEND\n"
1792 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1793 "#else\n"
1794 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1795 "#endif\n"
1796 "#endif\n"
1797 "\n"
1798 "#ifdef USEFOG\n"
1799 "       color.rgb = FogVertex(color.rgb);\n"
1800 "#endif\n"
1801 "\n"
1802 "       // 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"
1803 "#ifdef USEREFLECTION\n"
1804 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1805 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1806 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1807 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1808 "       // FIXME temporary hack to detect the case that the reflection\n"
1809 "       // gets blackened at edges due to leaving the area that contains actual\n"
1810 "       // content.\n"
1811 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1812 "       // 'appening.\n"
1813 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1814 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1815 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1816 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1817 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1818 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1819 "#endif\n"
1820 "\n"
1821 "       gl_FragColor = vec4(color);\n"
1822 "}\n"
1823 "#endif // FRAGMENT_SHADER\n"
1824 "\n"
1825 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1826 "#endif // !MODE_DEFERREDGEOMETRY\n"
1827 "#endif // !MODE_WATER\n"
1828 "#endif // !MODE_REFRACTION\n"
1829 "#endif // !MODE_BLOOMBLUR\n"
1830 "#endif // !MODE_GENERIC\n"
1831 "#endif // !MODE_POSTPROCESS\n"
1832 "#endif // !MODE_SHOWDEPTH\n"
1833 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1834 ;
1835
1836 /*
1837 =========================================================================================================================================================
1838
1839
1840
1841 =========================================================================================================================================================
1842
1843
1844
1845 =========================================================================================================================================================
1846
1847
1848
1849 =========================================================================================================================================================
1850
1851
1852
1853 =========================================================================================================================================================
1854
1855
1856
1857 =========================================================================================================================================================
1858
1859
1860
1861 =========================================================================================================================================================
1862 */
1863
1864 const char *builtincgshaderstring =
1865 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1866 "// written by Forest 'LordHavoc' Hale\n"
1867 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1868 "\n"
1869 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1870 "#if defined(USEREFLECTION)\n"
1871 "#undef USESHADOWMAPORTHO\n"
1872 "#endif\n"
1873 "\n"
1874 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1875 "# define USEFOG\n"
1876 "#endif\n"
1877 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1878 "#define USELIGHTMAP\n"
1879 "#endif\n"
1880 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
1881 "#define USEEYEVECTOR\n"
1882 "#endif\n"
1883 "\n"
1884 "#ifdef FRAGMENT_SHADER\n"
1885 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1886 "#endif\n"
1887 "\n"
1888 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1889 "#ifdef VERTEX_SHADER\n"
1890 "void main\n"
1891 "(\n"
1892 "float4 gl_Vertex : POSITION,\n"
1893 "uniform float4x4 ModelViewProjectionMatrix,\n"
1894 "out float4 gl_Position : POSITION\n"
1895 ")\n"
1896 "{\n"
1897 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1898 "}\n"
1899 "#endif\n"
1900 "#else // !MODE_DEPTH_ORSHADOW\n"
1901 "\n"
1902 "\n"
1903 "\n"
1904 "\n"
1905 "#ifdef MODE_SHOWDEPTH\n"
1906 "#ifdef VERTEX_SHADER\n"
1907 "void main\n"
1908 "(\n"
1909 "float4 gl_Vertex : POSITION,\n"
1910 "uniform float4x4 ModelViewProjectionMatrix,\n"
1911 "out float4 gl_Position : POSITION,\n"
1912 "out float4 gl_FrontColor : COLOR0\n"
1913 ")\n"
1914 "{\n"
1915 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1916 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1917 "}\n"
1918 "#endif\n"
1919 "\n"
1920 "#ifdef FRAGMENT_SHADER\n"
1921 "void main\n"
1922 "(\n"
1923 "float4 gl_FrontColor : COLOR0,\n"
1924 "out float4 gl_FragColor : COLOR\n"
1925 ")\n"
1926 "{\n"
1927 "       gl_FragColor = gl_FrontColor;\n"
1928 "}\n"
1929 "#endif\n"
1930 "#else // !MODE_SHOWDEPTH\n"
1931 "\n"
1932 "\n"
1933 "\n"
1934 "\n"
1935 "#ifdef MODE_POSTPROCESS\n"
1936 "\n"
1937 "#ifdef VERTEX_SHADER\n"
1938 "void main\n"
1939 "(\n"
1940 "float4 gl_Vertex : POSITION,\n"
1941 "uniform float4x4 ModelViewProjectionMatrix,\n"
1942 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1943 "float4 gl_MultiTexCoord1 : TEXCOORD4,\n"
1944 "out float4 gl_Position : POSITION,\n"
1945 "out float2 TexCoord1 : TEXCOORD0,\n"
1946 "out float2 TexCoord2 : TEXCOORD1\n"
1947 ")\n"
1948 "{\n"
1949 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1950 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1951 "#ifdef USEBLOOM\n"
1952 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1953 "#endif\n"
1954 "}\n"
1955 "#endif\n"
1956 "\n"
1957 "#ifdef FRAGMENT_SHADER\n"
1958 "void main\n"
1959 "(\n"
1960 "float2 TexCoord1 : TEXCOORD0,\n"
1961 "float2 TexCoord2 : TEXCOORD1,\n"
1962 "uniform sampler2D Texture_First,\n"
1963 "#ifdef USEBLOOM\n"
1964 "uniform sampler2D Texture_Second,\n"
1965 "#endif\n"
1966 "#ifdef USEGAMMARAMPS\n"
1967 "uniform sampler2D Texture_GammaRamps,\n"
1968 "#endif\n"
1969 "#ifdef USESATURATION\n"
1970 "uniform float Saturation,\n"
1971 "#endif\n"
1972 "#ifdef USEVIEWTINT\n"
1973 "uniform float4 ViewTintColor,\n"
1974 "#endif\n"
1975 "uniform float4 UserVec1,\n"
1976 "uniform float4 UserVec2,\n"
1977 "uniform float4 UserVec3,\n"
1978 "uniform float4 UserVec4,\n"
1979 "uniform float ClientTime,\n"
1980 "uniform float2 PixelSize,\n"
1981 "out float4 gl_FragColor : COLOR\n"
1982 ")\n"
1983 "{\n"
1984 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1985 "#ifdef USEBLOOM\n"
1986 "       gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
1987 "#endif\n"
1988 "#ifdef USEVIEWTINT\n"
1989 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1990 "#endif\n"
1991 "\n"
1992 "#ifdef USEPOSTPROCESSING\n"
1993 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1994 "// 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"
1995 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1996 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1997 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1998 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
1999 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
2000 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
2001 "#endif\n"
2002 "\n"
2003 "#ifdef USESATURATION\n"
2004 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2005 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2006 "       //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2007 "       gl_FragColor.rgb = lerp(float3(y), gl_FragColor.rgb, Saturation);\n"
2008 "#endif\n"
2009 "\n"
2010 "#ifdef USEGAMMARAMPS\n"
2011 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2012 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2013 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2014 "#endif\n"
2015 "}\n"
2016 "#endif\n"
2017 "#else // !MODE_POSTPROCESS\n"
2018 "\n"
2019 "\n"
2020 "\n"
2021 "\n"
2022 "#ifdef MODE_GENERIC\n"
2023 "#ifdef VERTEX_SHADER\n"
2024 "void main\n"
2025 "(\n"
2026 "float4 gl_Vertex : POSITION,\n"
2027 "uniform float4x4 ModelViewProjectionMatrix,\n"
2028 "float4 gl_Color : COLOR0,\n"
2029 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2030 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2031 "out float4 gl_Position : POSITION,\n"
2032 "out float4 gl_FrontColor : COLOR,\n"
2033 "out float2 TexCoord1 : TEXCOORD0,\n"
2034 "out float2 TexCoord2 : TEXCOORD1\n"
2035 ")\n"
2036 "{\n"
2037 "       gl_FrontColor = gl_Color;\n"
2038 "#ifdef USEDIFFUSE\n"
2039 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2040 "#endif\n"
2041 "#ifdef USESPECULAR\n"
2042 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
2043 "#endif\n"
2044 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2045 "}\n"
2046 "#endif\n"
2047 "\n"
2048 "#ifdef FRAGMENT_SHADER\n"
2049 "\n"
2050 "void main\n"
2051 "(\n"
2052 "float4 gl_FrontColor : COLOR,\n"
2053 "float2 TexCoord1 : TEXCOORD0,\n"
2054 "float2 TexCoord2 : TEXCOORD1,\n"
2055 "#ifdef USEDIFFUSE\n"
2056 "uniform sampler2D Texture_First,\n"
2057 "#endif\n"
2058 "#ifdef USESPECULAR\n"
2059 "uniform sampler2D Texture_Second,\n"
2060 "#endif\n"
2061 "out float4 gl_FragColor : COLOR\n"
2062 ")\n"
2063 "{\n"
2064 "       gl_FragColor = gl_FrontColor;\n"
2065 "#ifdef USEDIFFUSE\n"
2066 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2067 "#endif\n"
2068 "\n"
2069 "#ifdef USESPECULAR\n"
2070 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2071 "# ifdef USECOLORMAPPING\n"
2072 "       gl_FragColor *= tex2;\n"
2073 "# endif\n"
2074 "# ifdef USEGLOW\n"
2075 "       gl_FragColor += tex2;\n"
2076 "# endif\n"
2077 "# ifdef USEVERTEXTEXTUREBLEND\n"
2078 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2079 "# endif\n"
2080 "#endif\n"
2081 "}\n"
2082 "#endif\n"
2083 "#else // !MODE_GENERIC\n"
2084 "\n"
2085 "\n"
2086 "\n"
2087 "\n"
2088 "#ifdef MODE_BLOOMBLUR\n"
2089 "#ifdef VERTEX_SHADER\n"
2090 "void main\n"
2091 "(\n"
2092 "float4 gl_Vertex : POSITION,\n"
2093 "uniform float4x4 ModelViewProjectionMatrix,\n"
2094 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2095 "out float4 gl_Position : POSITION,\n"
2096 "out float2 TexCoord : TEXCOORD0\n"
2097 ")\n"
2098 "{\n"
2099 "       TexCoord = gl_MultiTexCoord0.xy;\n"
2100 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2101 "}\n"
2102 "#endif\n"
2103 "\n"
2104 "#ifdef FRAGMENT_SHADER\n"
2105 "\n"
2106 "void main\n"
2107 "(\n"
2108 "float2 TexCoord : TEXCOORD0,\n"
2109 "uniform sampler2D Texture_First,\n"
2110 "uniform float4 BloomBlur_Parameters,\n"
2111 "out float4 gl_FragColor : COLOR\n"
2112 ")\n"
2113 "{\n"
2114 "       int i;\n"
2115 "       float2 tc = TexCoord;\n"
2116 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2117 "       tc += BloomBlur_Parameters.xy;\n"
2118 "       for (i = 1;i < SAMPLES;i++)\n"
2119 "       {\n"
2120 "               color += tex2D(Texture_First, tc).rgb;\n"
2121 "               tc += BloomBlur_Parameters.xy;\n"
2122 "       }\n"
2123 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2124 "}\n"
2125 "#endif\n"
2126 "#else // !MODE_BLOOMBLUR\n"
2127 "#ifdef MODE_REFRACTION\n"
2128 "#ifdef VERTEX_SHADER\n"
2129 "void main\n"
2130 "(\n"
2131 "float4 gl_Vertex : POSITION,\n"
2132 "uniform float4x4 ModelViewProjectionMatrix,\n"
2133 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2134 "uniform float4x4 TexMatrix,\n"
2135 "uniform float3 EyePosition,\n"
2136 "out float4 gl_Position : POSITION,\n"
2137 "out float2 TexCoord : TEXCOORD0,\n"
2138 "out float3 EyeVector : TEXCOORD1,\n"
2139 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2140 ")\n"
2141 "{\n"
2142 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2143 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2144 "       ModelViewProjectionPosition = gl_Position;\n"
2145 "}\n"
2146 "#endif\n"
2147 "\n"
2148 "#ifdef FRAGMENT_SHADER\n"
2149 "void main\n"
2150 "(\n"
2151 "float2 TexCoord : TEXCOORD0,\n"
2152 "float3 EyeVector : TEXCOORD1,\n"
2153 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2154 "uniform sampler2D Texture_Normal,\n"
2155 "uniform sampler2D Texture_Refraction,\n"
2156 "uniform sampler2D Texture_Reflection,\n"
2157 "uniform float4 DistortScaleRefractReflect,\n"
2158 "uniform float4 ScreenScaleRefractReflect,\n"
2159 "uniform float4 ScreenCenterRefractReflect,\n"
2160 "uniform float4 RefractColor,\n"
2161 "out float4 gl_FragColor : COLOR\n"
2162 ")\n"
2163 "{\n"
2164 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2165 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2166 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2167 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
2168 "       // FIXME temporary hack to detect the case that the reflection\n"
2169 "       // gets blackened at edges due to leaving the area that contains actual\n"
2170 "       // content.\n"
2171 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2172 "       // 'appening.\n"
2173 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2174 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2175 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2176 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2177 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2178 "       gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2179 "}\n"
2180 "#endif\n"
2181 "#else // !MODE_REFRACTION\n"
2182 "\n"
2183 "\n"
2184 "\n"
2185 "\n"
2186 "#ifdef MODE_WATER\n"
2187 "#ifdef VERTEX_SHADER\n"
2188 "\n"
2189 "void main\n"
2190 "(\n"
2191 "float4 gl_Vertex : POSITION,\n"
2192 "uniform float4x4 ModelViewProjectionMatrix,\n"
2193 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2194 "uniform float4x4 TexMatrix,\n"
2195 "uniform float3 EyePosition,\n"
2196 "out float4 gl_Position : POSITION,\n"
2197 "out float2 TexCoord : TEXCOORD0,\n"
2198 "out float3 EyeVector : TEXCOORD1,\n"
2199 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2200 ")\n"
2201 "{\n"
2202 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2203 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2204 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2205 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2206 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2207 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2208 "       ModelViewProjectionPosition = gl_Position;\n"
2209 "}\n"
2210 "#endif\n"
2211 "\n"
2212 "#ifdef FRAGMENT_SHADER\n"
2213 "void main\n"
2214 "(\n"
2215 "float2 TexCoord : TEXCOORD0,\n"
2216 "float3 EyeVector : TEXCOORD1,\n"
2217 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2218 "uniform sampler2D Texture_Normal,\n"
2219 "uniform sampler2D Texture_Refraction,\n"
2220 "uniform sampler2D Texture_Reflection,\n"
2221 "uniform float4 DistortScaleRefractReflect,\n"
2222 "uniform float4 ScreenScaleRefractReflect,\n"
2223 "uniform float4 ScreenCenterRefractReflect,\n"
2224 "uniform float4 RefractColor,\n"
2225 "uniform float4 ReflectColor,\n"
2226 "uniform float ReflectFactor,\n"
2227 "uniform float ReflectOffset,\n"
2228 "out float4 gl_FragColor : COLOR\n"
2229 ")\n"
2230 "{\n"
2231 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2232 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2233 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2234 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xyxy * DistortScaleRefractReflect;\n"
2235 "       // FIXME temporary hack to detect the case that the reflection\n"
2236 "       // gets blackened at edges due to leaving the area that contains actual\n"
2237 "       // content.\n"
2238 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2239 "       // 'appening.\n"
2240 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2241 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2242 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2243 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2244 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2245 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2246 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2247 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2248 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2249 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2250 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2251 "       gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2252 "}\n"
2253 "#endif\n"
2254 "#else // !MODE_WATER\n"
2255 "\n"
2256 "\n"
2257 "\n"
2258 "\n"
2259 "// 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"
2260 "\n"
2261 "// fragment shader specific:\n"
2262 "#ifdef FRAGMENT_SHADER\n"
2263 "\n"
2264 "#ifdef USEFOG\n"
2265 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask, sampler2D Texture_FogHeightTexture)\n"
2266 "{\n"
2267 "       float fogfrac;\n"
2268 "#ifdef USEFOGHEIGHTTEXTURE\n"
2269 "       float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2270 "       fogfrac = fogheightpixel.a;\n"
2271 "       return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2272 "#else\n"
2273 "# ifdef USEFOGOUTSIDE\n"
2274 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2275 "# else\n"
2276 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2277 "# endif\n"
2278 "       return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2279 "#endif\n"
2280 "}\n"
2281 "#endif\n"
2282 "\n"
2283 "#ifdef USEOFFSETMAPPING\n"
2284 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler2D Texture_Normal)\n"
2285 "{\n"
2286 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2287 "       // 14 sample relief mapping: linear search and then binary search\n"
2288 "       // this basically steps forward a small amount repeatedly until it finds\n"
2289 "       // itself inside solid, then jitters forward and back using decreasing\n"
2290 "       // amounts to find the impact\n"
2291 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2292 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2293 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2294 "       float3 RT = float3(TexCoord, 1);\n"
2295 "       OffsetVector *= 0.1;\n"
2296 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2297 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2298 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2299 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2300 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2301 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2302 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2303 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2304 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2305 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2306 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2307 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2308 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2309 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2310 "       return RT.xy;\n"
2311 "#else\n"
2312 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2313 "       // this basically moves forward the full distance, and then backs up based\n"
2314 "       // on height of samples\n"
2315 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2316 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2317 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2318 "       TexCoord += OffsetVector;\n"
2319 "       OffsetVector *= 0.333;\n"
2320 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2321 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2322 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2323 "       return TexCoord;\n"
2324 "#endif\n"
2325 "}\n"
2326 "#endif // USEOFFSETMAPPING\n"
2327 "\n"
2328 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2329 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2330 "# ifdef USESHADOWMAPORTHO\n"
2331 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2332 "# else\n"
2333 "#  ifdef USESHADOWMAPVSDCT\n"
2334 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2335 "{\n"
2336 "       float3 adir = abs(dir);\n"
2337 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2338 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2339 "       return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2340 "}\n"
2341 "#  else\n"
2342 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2343 "{\n"
2344 "       float3 adir = abs(dir);\n"
2345 "       float ma = adir.z;\n"
2346 "       float4 proj = float4(dir, 2.5);\n"
2347 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2348 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2349 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2350 "       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"
2351 "}\n"
2352 "#  endif\n"
2353 "# endif\n"
2354 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2355 "\n"
2356 "#ifdef USESHADOWMAPCUBE\n"
2357 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2358 "{\n"
2359 "    float3 adir = abs(dir);\n"
2360 "    return float4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
2361 "}\n"
2362 "#endif\n"
2363 "\n"
2364 "# ifdef USESHADOWMAPRECT\n"
2365 "#ifdef USESHADOWMAPVSDCT\n"
2366 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2367 "#else\n"
2368 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2369 "#endif\n"
2370 "{\n"
2371 "#ifdef USESHADOWMAPVSDCT\n"
2372 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2373 "#else\n"
2374 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2375 "#endif\n"
2376 "       float f;\n"
2377 "#  ifdef USESHADOWSAMPLER\n"
2378 "\n"
2379 "#    ifdef USESHADOWMAPPCF\n"
2380 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2381 "    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"
2382 "#    else\n"
2383 "    f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2384 "#    endif\n"
2385 "\n"
2386 "#  else\n"
2387 "\n"
2388 "#    ifdef USESHADOWMAPPCF\n"
2389 "#      if USESHADOWMAPPCF > 1\n"
2390 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2391 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2392 "    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"
2393 "    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"
2394 "    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"
2395 "    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"
2396 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2397 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2398 "#      else\n"
2399 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2400 "    float2 offset = frac(shadowmaptc.xy);\n"
2401 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2402 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2403 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2404 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2405 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2406 "#      endif\n"
2407 "#    else\n"
2408 "    f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2409 "#    endif\n"
2410 "\n"
2411 "#  endif\n"
2412 "#  ifdef USESHADOWMAPORTHO\n"
2413 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2414 "#  else\n"
2415 "       return f;\n"
2416 "#  endif\n"
2417 "}\n"
2418 "# endif\n"
2419 "\n"
2420 "# ifdef USESHADOWMAP2D\n"
2421 "#ifdef USESHADOWMAPVSDCT\n"
2422 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2423 "#else\n"
2424 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2425 "#endif\n"
2426 "{\n"
2427 "#ifdef USESHADOWMAPVSDCT\n"
2428 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2429 "#else\n"
2430 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2431 "#endif\n"
2432 "    float f;\n"
2433 "\n"
2434 "#  ifdef USESHADOWSAMPLER\n"
2435 "#    ifdef USESHADOWMAPPCF\n"
2436 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, float3(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
2437 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2438 "    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"
2439 "#    else\n"
2440 "    f = shadow2D(Texture_ShadowMap2D, float3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
2441 "#    endif\n"
2442 "#  else\n"
2443 "#    ifdef USESHADOWMAPPCF\n"
2444 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2445 "#      ifdef GL_ARB_texture_gather\n"
2446 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
2447 "#      else\n"
2448 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x,y)*ShadowMap_TextureScale)\n"
2449 "#      endif\n"
2450 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2451 "    center *= ShadowMap_TextureScale;\n"
2452 "    float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2453 "    float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2454 "    float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2455 "    float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2456 "    float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2457 "                lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2458 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2459 "#     else\n"
2460 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)  \n"
2461 "#      if USESHADOWMAPPCF > 1\n"
2462 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2463 "    center *= ShadowMap_TextureScale;\n"
2464 "    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"
2465 "    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"
2466 "    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"
2467 "    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"
2468 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2469 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2470 "#      else\n"
2471 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2472 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2473 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2474 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2475 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2476 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2477 "#      endif\n"
2478 "#     endif\n"
2479 "#    else\n"
2480 "    f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2481 "#    endif\n"
2482 "#  endif\n"
2483 "#  ifdef USESHADOWMAPORTHO\n"
2484 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2485 "#  else\n"
2486 "       return f;\n"
2487 "#  endif\n"
2488 "}\n"
2489 "# endif\n"
2490 "\n"
2491 "# ifdef USESHADOWMAPCUBE\n"
2492 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2493 "{\n"
2494 "    // apply depth texture cubemap as light filter\n"
2495 "    float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2496 "    float f;\n"
2497 "#  ifdef USESHADOWSAMPLER\n"
2498 "    f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2499 "#  else\n"
2500 "    f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2501 "#  endif\n"
2502 "    return f;\n"
2503 "}\n"
2504 "# endif\n"
2505 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2506 "#endif // FRAGMENT_SHADER\n"
2507 "\n"
2508 "\n"
2509 "\n"
2510 "\n"
2511 "#ifdef MODE_DEFERREDGEOMETRY\n"
2512 "#ifdef VERTEX_SHADER\n"
2513 "void main\n"
2514 "(\n"
2515 "float4 gl_Vertex : POSITION,\n"
2516 "uniform float4x4 ModelViewProjectionMatrix,\n"
2517 "#ifdef USEVERTEXTEXTUREBLEND\n"
2518 "float4 gl_Color : COLOR0,\n"
2519 "#endif\n"
2520 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2521 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2522 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2523 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2524 "uniform float4x4 TexMatrix,\n"
2525 "#ifdef USEVERTEXTEXTUREBLEND\n"
2526 "uniform float4x4 BackgroundTexMatrix,\n"
2527 "#endif\n"
2528 "uniform float4x4 ModelViewMatrix,\n"
2529 "#ifdef USEOFFSETMAPPING\n"
2530 "uniform float3 EyePosition,\n"
2531 "#endif\n"
2532 "out float4 gl_Position : POSITION,\n"
2533 "out float4 gl_FrontColor : COLOR,\n"
2534 "out float4 TexCoordBoth : TEXCOORD0,\n"
2535 "#ifdef USEOFFSETMAPPING\n"
2536 "out float3 EyeVector : TEXCOORD2,\n"
2537 "#endif\n"
2538 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2539 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2540 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2541 ")\n"
2542 "{\n"
2543 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2544 "#ifdef USEVERTEXTEXTUREBLEND\n"
2545 "       gl_FrontColor = gl_Color;\n"
2546 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2547 "#endif\n"
2548 "\n"
2549 "       // transform unnormalized eye direction into tangent space\n"
2550 "#ifdef USEOFFSETMAPPING\n"
2551 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2552 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2553 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2554 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2555 "#endif\n"
2556 "\n"
2557 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2558 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2559 "       VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2560 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2561 "}\n"
2562 "#endif // VERTEX_SHADER\n"
2563 "\n"
2564 "#ifdef FRAGMENT_SHADER\n"
2565 "void main\n"
2566 "(\n"
2567 "float4 TexCoordBoth : TEXCOORD0,\n"
2568 "float3 EyeVector : TEXCOORD2,\n"
2569 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2570 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2571 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2572 "uniform sampler2D Texture_Normal,\n"
2573 "#ifdef USEALPHAKILL\n"
2574 "uniform sampler2D Texture_Color,\n"
2575 "#endif\n"
2576 "uniform sampler2D Texture_Gloss,\n"
2577 "#ifdef USEVERTEXTEXTUREBLEND\n"
2578 "uniform sampler2D Texture_SecondaryNormal,\n"
2579 "uniform sampler2D Texture_SecondaryGloss,\n"
2580 "#endif\n"
2581 "#ifdef USEOFFSETMAPPING\n"
2582 "uniform float OffsetMapping_Scale,\n"
2583 "#endif\n"
2584 "uniform half SpecularPower,\n"
2585 "out float4 gl_FragColor : COLOR\n"
2586 ")\n"
2587 "{\n"
2588 "       float2 TexCoord = TexCoordBoth.xy;\n"
2589 "#ifdef USEOFFSETMAPPING\n"
2590 "       // apply offsetmapping\n"
2591 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2592 "#define TexCoord TexCoordOffset\n"
2593 "#endif\n"
2594 "\n"
2595 "#ifdef USEALPHAKILL\n"
2596 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2597 "               discard;\n"
2598 "#endif\n"
2599 "\n"
2600 "#ifdef USEVERTEXTEXTUREBLEND\n"
2601 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2602 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2603 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2604 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2605 "#endif\n"
2606 "\n"
2607 "#ifdef USEVERTEXTEXTUREBLEND\n"
2608 "       float3 surfacenormal = lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
2609 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2610 "#else\n"
2611 "       float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
2612 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2613 "#endif\n"
2614 "\n"
2615 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), 1);\n"
2616 "}\n"
2617 "#endif // FRAGMENT_SHADER\n"
2618 "#else // !MODE_DEFERREDGEOMETRY\n"
2619 "\n"
2620 "\n"
2621 "\n"
2622 "\n"
2623 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2624 "#ifdef VERTEX_SHADER\n"
2625 "void main\n"
2626 "(\n"
2627 "float4 gl_Vertex : POSITION,\n"
2628 "uniform float4x4 ModelViewProjectionMatrix,\n"
2629 "uniform float4x4 ModelViewMatrix,\n"
2630 "out float4 gl_Position : POSITION,\n"
2631 "out float4 ModelViewPosition : TEXCOORD0\n"
2632 ")\n"
2633 "{\n"
2634 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2635 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2636 "}\n"
2637 "#endif // VERTEX_SHADER\n"
2638 "\n"
2639 "#ifdef FRAGMENT_SHADER\n"
2640 "void main\n"
2641 "(\n"
2642 "float2 Pixel : WPOS,\n"
2643 "float4 ModelViewPosition : TEXCOORD0,\n"
2644 "uniform float4x4 ViewToLight,\n"
2645 "uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2646 "uniform float3 LightPosition,\n"
2647 "uniform half2 PixelToScreenTexCoord,\n"
2648 "uniform half3 DeferredColor_Ambient,\n"
2649 "uniform half3 DeferredColor_Diffuse,\n"
2650 "#ifdef USESPECULAR\n"
2651 "uniform half3 DeferredColor_Specular,\n"
2652 "uniform half SpecularPower,\n"
2653 "#endif\n"
2654 "uniform sampler2D Texture_Attenuation,\n"
2655 "uniform sampler2D Texture_ScreenDepth,\n"
2656 "uniform sampler2D Texture_ScreenNormalMap,\n"
2657 "\n"
2658 "#ifdef USECUBEFILTER\n"
2659 "uniform samplerCUBE Texture_Cube,\n"
2660 "#endif\n"
2661 "\n"
2662 "#ifdef USESHADOWMAPRECT\n"
2663 "# ifdef USESHADOWSAMPLER\n"
2664 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2665 "# else\n"
2666 "uniform samplerRECT Texture_ShadowMapRect,\n"
2667 "# endif\n"
2668 "#endif\n"
2669 "\n"
2670 "#ifdef USESHADOWMAP2D\n"
2671 "# ifdef USESHADOWSAMPLER\n"
2672 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2673 "# else\n"
2674 "uniform sampler2D Texture_ShadowMap2D,\n"
2675 "# endif\n"
2676 "#endif\n"
2677 "\n"
2678 "#ifdef USESHADOWMAPVSDCT\n"
2679 "uniform samplerCUBE Texture_CubeProjection,\n"
2680 "#endif\n"
2681 "\n"
2682 "#ifdef USESHADOWMAPCUBE\n"
2683 "# ifdef USESHADOWSAMPLER\n"
2684 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2685 "# else\n"
2686 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2687 "# endif\n"
2688 "#endif\n"
2689 "\n"
2690 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2691 "uniform float2 ShadowMap_TextureScale,\n"
2692 "uniform float4 ShadowMap_Parameters,\n"
2693 "#endif\n"
2694 "\n"
2695 "out float4 gl_FragData0 : COLOR0,\n"
2696 "out float4 gl_FragData1 : COLOR1\n"
2697 ")\n"
2698 "{\n"
2699 "       // calculate viewspace pixel position\n"
2700 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2701 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2702 "       float3 position;\n"
2703 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2704 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2705 "       // decode viewspace pixel normal\n"
2706 "       half4 normalmap = tex2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
2707 "       half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
2708 "       // surfacenormal = pixel normal in viewspace\n"
2709 "       // LightVector = pixel to light in viewspace\n"
2710 "       // CubeVector = position in lightspace\n"
2711 "       // eyevector = pixel to view in viewspace\n"
2712 "       float3 CubeVector = float3(mul(ViewToLight, float4(position,1)));\n"
2713 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2714 "#ifdef USEDIFFUSE\n"
2715 "       // calculate diffuse shading\n"
2716 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2717 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2718 "#endif\n"
2719 "#ifdef USESPECULAR\n"
2720 "       // calculate directional shading\n"
2721 "       float3 eyevector = position * -1.0;\n"
2722 "#  ifdef USEEXACTSPECULARMATH\n"
2723 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
2724 "#  else\n"
2725 "       half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
2726 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
2727 "#  endif\n"
2728 "#endif\n"
2729 "\n"
2730 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2731 "       fade *= ShadowMapCompare(CubeVector,\n"
2732 "# if defined(USESHADOWMAP2D)\n"
2733 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2734 "# endif\n"
2735 "# if defined(USESHADOWMAPRECT)\n"
2736 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2737 "# endif\n"
2738 "# if defined(USESHADOWMAPCUBE)\n"
2739 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2740 "# endif\n"
2741 "\n"
2742 "#ifdef USESHADOWMAPVSDCT\n"
2743 ", Texture_CubeProjection\n"
2744 "#endif\n"
2745 "       );\n"
2746 "#endif\n"
2747 "\n"
2748 "#ifdef USEDIFFUSE\n"
2749 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2750 "#else\n"
2751 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2752 "#endif\n"
2753 "#ifdef USESPECULAR\n"
2754 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2755 "#else\n"
2756 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2757 "#endif\n"
2758 "\n"
2759 "# ifdef USECUBEFILTER\n"
2760 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2761 "       gl_FragData0.rgb *= cubecolor;\n"
2762 "       gl_FragData1.rgb *= cubecolor;\n"
2763 "# endif\n"
2764 "}\n"
2765 "#endif // FRAGMENT_SHADER\n"
2766 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2767 "\n"
2768 "\n"
2769 "\n"
2770 "\n"
2771 "#ifdef VERTEX_SHADER\n"
2772 "void main\n"
2773 "(\n"
2774 "float4 gl_Vertex : POSITION,\n"
2775 "uniform float4x4 ModelViewProjectionMatrix,\n"
2776 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2777 "float4 gl_Color : COLOR0,\n"
2778 "#endif\n"
2779 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2780 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2781 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2782 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2783 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2784 "\n"
2785 "uniform float3 EyePosition,\n"
2786 "uniform float4x4 TexMatrix,\n"
2787 "#ifdef USEVERTEXTEXTUREBLEND\n"
2788 "uniform float4x4 BackgroundTexMatrix,\n"
2789 "#endif\n"
2790 "#ifdef MODE_LIGHTSOURCE\n"
2791 "uniform float4x4 ModelToLight,\n"
2792 "#endif\n"
2793 "#ifdef MODE_LIGHTSOURCE\n"
2794 "uniform float3 LightPosition,\n"
2795 "#endif\n"
2796 "#ifdef MODE_LIGHTDIRECTION\n"
2797 "uniform float3 LightDir,\n"
2798 "#endif\n"
2799 "uniform float4 FogPlane,\n"
2800 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2801 "uniform float3 LightPosition,\n"
2802 "#endif\n"
2803 "#ifdef USESHADOWMAPORTHO\n"
2804 "uniform float4x4 ShadowMapMatrix,\n"
2805 "#endif\n"
2806 "\n"
2807 "out float4 gl_FrontColor : COLOR,\n"
2808 "out float4 TexCoordBoth : TEXCOORD0,\n"
2809 "#ifdef USELIGHTMAP\n"
2810 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2811 "#endif\n"
2812 "#ifdef USEEYEVECTOR\n"
2813 "out float3 EyeVector : TEXCOORD2,\n"
2814 "#endif\n"
2815 "#ifdef USEREFLECTION\n"
2816 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2817 "#endif\n"
2818 "#ifdef USEFOG\n"
2819 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2820 "#endif\n"
2821 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2822 "out float3 LightVector : TEXCOORD1,\n"
2823 "#endif\n"
2824 "#ifdef MODE_LIGHTSOURCE\n"
2825 "out float3 CubeVector : TEXCOORD3,\n"
2826 "#endif\n"
2827 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2828 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2829 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2830 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2831 "#endif\n"
2832 "#ifdef USESHADOWMAPORTHO\n"
2833 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2834 "#endif\n"
2835 "out float4 gl_Position : POSITION\n"
2836 ")\n"
2837 "{\n"
2838 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2839 "       gl_FrontColor = gl_Color;\n"
2840 "#endif\n"
2841 "       // copy the surface texcoord\n"
2842 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2843 "#ifdef USEVERTEXTEXTUREBLEND\n"
2844 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2845 "#endif\n"
2846 "#ifdef USELIGHTMAP\n"
2847 "       TexCoordLightmap = float2(gl_MultiTexCoord4);\n"
2848 "#endif\n"
2849 "\n"
2850 "#ifdef MODE_LIGHTSOURCE\n"
2851 "       // transform vertex position into light attenuation/cubemap space\n"
2852 "       // (-1 to +1 across the light box)\n"
2853 "       CubeVector = float3(mul(ModelToLight, gl_Vertex));\n"
2854 "\n"
2855 "# ifdef USEDIFFUSE\n"
2856 "       // transform unnormalized light direction into tangent space\n"
2857 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2858 "       //  normalize it per pixel)\n"
2859 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2860 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2861 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2862 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2863 "# endif\n"
2864 "#endif\n"
2865 "\n"
2866 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2867 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2868 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2869 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2870 "#endif\n"
2871 "\n"
2872 "       // transform unnormalized eye direction into tangent space\n"
2873 "#ifdef USEEYEVECTOR\n"
2874 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2875 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2876 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2877 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2878 "#endif\n"
2879 "\n"
2880 "#ifdef USEFOG\n"
2881 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2882 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2883 "#endif\n"
2884 "\n"
2885 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2886 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2887 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2888 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2889 "#endif\n"
2890 "\n"
2891 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2892 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2893 "\n"
2894 "#ifdef USESHADOWMAPORTHO\n"
2895 "       ShadowMapTC = float3(mul(ShadowMapMatrix, gl_Position));\n"
2896 "#endif\n"
2897 "\n"
2898 "#ifdef USEREFLECTION\n"
2899 "       ModelViewProjectionPosition = gl_Position;\n"
2900 "#endif\n"
2901 "}\n"
2902 "#endif // VERTEX_SHADER\n"
2903 "\n"
2904 "\n"
2905 "\n"
2906 "\n"
2907 "#ifdef FRAGMENT_SHADER\n"
2908 "void main\n"
2909 "(\n"
2910 "#ifdef USEDEFERREDLIGHTMAP\n"
2911 "float2 Pixel : WPOS,\n"
2912 "#endif\n"
2913 "float4 gl_FrontColor : COLOR,\n"
2914 "float4 TexCoordBoth : TEXCOORD0,\n"
2915 "#ifdef USELIGHTMAP\n"
2916 "float2 TexCoordLightmap : TEXCOORD1,\n"
2917 "#endif\n"
2918 "#ifdef USEEYEVECTOR\n"
2919 "float3 EyeVector : TEXCOORD2,\n"
2920 "#endif\n"
2921 "#ifdef USEREFLECTION\n"
2922 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2923 "#endif\n"
2924 "#ifdef USEFOG\n"
2925 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2926 "#endif\n"
2927 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2928 "float3 LightVector : TEXCOORD1,\n"
2929 "#endif\n"
2930 "#ifdef MODE_LIGHTSOURCE\n"
2931 "float3 CubeVector : TEXCOORD3,\n"
2932 "#endif\n"
2933 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2934 "float4 ModelViewPosition : TEXCOORD0,\n"
2935 "#endif\n"
2936 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2937 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2938 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2939 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2940 "#endif\n"
2941 "#ifdef USESHADOWMAPORTHO\n"
2942 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2943 "#endif\n"
2944 "\n"
2945 "uniform sampler2D Texture_Normal,\n"
2946 "uniform sampler2D Texture_Color,\n"
2947 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2948 "uniform sampler2D Texture_Gloss,\n"
2949 "#endif\n"
2950 "#ifdef USEGLOW\n"
2951 "uniform sampler2D Texture_Glow,\n"
2952 "#endif\n"
2953 "#ifdef USEVERTEXTEXTUREBLEND\n"
2954 "uniform sampler2D Texture_SecondaryNormal,\n"
2955 "uniform sampler2D Texture_SecondaryColor,\n"
2956 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2957 "uniform sampler2D Texture_SecondaryGloss,\n"
2958 "#endif\n"
2959 "#ifdef USEGLOW\n"
2960 "uniform sampler2D Texture_SecondaryGlow,\n"
2961 "#endif\n"
2962 "#endif\n"
2963 "#ifdef USECOLORMAPPING\n"
2964 "uniform sampler2D Texture_Pants,\n"
2965 "uniform sampler2D Texture_Shirt,\n"
2966 "#endif\n"
2967 "#ifdef USEFOG\n"
2968 "uniform sampler2D Texture_FogHeightTexture,\n"
2969 "uniform sampler2D Texture_FogMask,\n"
2970 "#endif\n"
2971 "#ifdef USELIGHTMAP\n"
2972 "uniform sampler2D Texture_Lightmap,\n"
2973 "#endif\n"
2974 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2975 "uniform sampler2D Texture_Deluxemap,\n"
2976 "#endif\n"
2977 "#ifdef USEREFLECTION\n"
2978 "uniform sampler2D Texture_Reflection,\n"
2979 "#endif\n"
2980 "\n"
2981 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2982 "uniform sampler2D Texture_ScreenDepth,\n"
2983 "uniform sampler2D Texture_ScreenNormalMap,\n"
2984 "#endif\n"
2985 "#ifdef USEDEFERREDLIGHTMAP\n"
2986 "uniform sampler2D Texture_ScreenDiffuse,\n"
2987 "uniform sampler2D Texture_ScreenSpecular,\n"
2988 "#endif\n"
2989 "\n"
2990 "#ifdef USECOLORMAPPING\n"
2991 "uniform half3 Color_Pants,\n"
2992 "uniform half3 Color_Shirt,\n"
2993 "#endif\n"
2994 "#ifdef USEFOG\n"
2995 "uniform float3 FogColor,\n"
2996 "uniform float FogRangeRecip,\n"
2997 "uniform float FogPlaneViewDist,\n"
2998 "uniform float FogHeightFade,\n"
2999 "#endif\n"
3000 "\n"
3001 "#ifdef USEOFFSETMAPPING\n"
3002 "uniform float OffsetMapping_Scale,\n"
3003 "#endif\n"
3004 "\n"
3005 "#ifdef USEDEFERREDLIGHTMAP\n"
3006 "uniform half2 PixelToScreenTexCoord,\n"
3007 "uniform half3 DeferredMod_Diffuse,\n"
3008 "uniform half3 DeferredMod_Specular,\n"
3009 "#endif\n"
3010 "uniform half3 Color_Ambient,\n"
3011 "uniform half3 Color_Diffuse,\n"
3012 "uniform half3 Color_Specular,\n"
3013 "uniform half SpecularPower,\n"
3014 "#ifdef USEGLOW\n"
3015 "uniform half3 Color_Glow,\n"
3016 "#endif\n"
3017 "uniform half Alpha,\n"
3018 "#ifdef USEREFLECTION\n"
3019 "uniform float4 DistortScaleRefractReflect,\n"
3020 "uniform float4 ScreenScaleRefractReflect,\n"
3021 "uniform float4 ScreenCenterRefractReflect,\n"
3022 "uniform half4 ReflectColor,\n"
3023 "#endif\n"
3024 "#ifdef USEREFLECTCUBE\n"
3025 "uniform float4x4 ModelToReflectCube,\n"
3026 "uniform sampler2D Texture_ReflectMask,\n"
3027 "uniform samplerCUBE Texture_ReflectCube,\n"
3028 "#endif\n"
3029 "#ifdef MODE_LIGHTDIRECTION\n"
3030 "uniform half3 LightColor,\n"
3031 "#endif\n"
3032 "#ifdef MODE_LIGHTSOURCE\n"
3033 "uniform half3 LightColor,\n"
3034 "#endif\n"
3035 "\n"
3036 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3037 "uniform sampler2D Texture_Attenuation,\n"
3038 "uniform samplerCUBE Texture_Cube,\n"
3039 "#endif\n"
3040 "\n"
3041 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3042 "\n"
3043 "#ifdef USESHADOWMAPRECT\n"
3044 "# ifdef USESHADOWSAMPLER\n"
3045 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
3046 "# else\n"
3047 "uniform samplerRECT Texture_ShadowMapRect,\n"
3048 "# endif\n"
3049 "#endif\n"
3050 "\n"
3051 "#ifdef USESHADOWMAP2D\n"
3052 "# ifdef USESHADOWSAMPLER\n"
3053 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
3054 "# else\n"
3055 "uniform sampler2D Texture_ShadowMap2D,\n"
3056 "# endif\n"
3057 "#endif\n"
3058 "\n"
3059 "#ifdef USESHADOWMAPVSDCT\n"
3060 "uniform samplerCUBE Texture_CubeProjection,\n"
3061 "#endif\n"
3062 "\n"
3063 "#ifdef USESHADOWMAPCUBE\n"
3064 "# ifdef USESHADOWSAMPLER\n"
3065 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
3066 "# else\n"
3067 "uniform samplerCUBE Texture_ShadowMapCube,\n"
3068 "# endif\n"
3069 "#endif\n"
3070 "\n"
3071 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
3072 "uniform float2 ShadowMap_TextureScale,\n"
3073 "uniform float4 ShadowMap_Parameters,\n"
3074 "#endif\n"
3075 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3076 "\n"
3077 "out float4 gl_FragColor : COLOR\n"
3078 ")\n"
3079 "{\n"
3080 "       float2 TexCoord = TexCoordBoth.xy;\n"
3081 "#ifdef USEVERTEXTEXTUREBLEND\n"
3082 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
3083 "#endif\n"
3084 "#ifdef USEOFFSETMAPPING\n"
3085 "       // apply offsetmapping\n"
3086 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3087 "#define TexCoord TexCoordOffset\n"
3088 "#endif\n"
3089 "\n"
3090 "       // combine the diffuse textures (base, pants, shirt)\n"
3091 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3092 "#ifdef USEALPHAKILL\n"
3093 "       if (color.a < 0.5)\n"
3094 "               discard;\n"
3095 "#endif\n"
3096 "       color.a *= Alpha;\n"
3097 "#ifdef USECOLORMAPPING\n"
3098 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord)) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
3099 "#endif\n"
3100 "#ifdef USEVERTEXTEXTUREBLEND\n"
3101 "       float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3102 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3103 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3104 "       color.rgb = half3(lerp(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
3105 "       color.a = 1.0;\n"
3106 "       //color = lerp(half4(1, 0, 0, 1), color, terrainblend);\n"
3107 "#endif\n"
3108 "\n"
3109 "       // get the surface normal\n"
3110 "#ifdef USEVERTEXTEXTUREBLEND\n"
3111 "       half3 surfacenormal = normalize(half3(lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3112 "#else\n"
3113 "       half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
3114 "#endif\n"
3115 "\n"
3116 "       // get the material colors\n"
3117 "       half3 diffusetex = color.rgb;\n"
3118 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3119 "# ifdef USEVERTEXTEXTUREBLEND\n"
3120 "       half4 glosstex = half4(lerp(float4(tex2D(Texture_SecondaryGloss, TexCoord2)), float4(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
3121 "# else\n"
3122 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3123 "# endif\n"
3124 "#endif\n"
3125 "\n"
3126 "#ifdef USEREFLECTCUBE\n"
3127 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3128 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3129 "       float3 ReflectCubeTexCoord = float3(mul(ModelToReflectCube, float4(ModelReflectVector, 0)));\n"
3130 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord)) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord));\n"
3131 "#endif\n"
3132 "\n"
3133 "\n"
3134 "\n"
3135 "\n"
3136 "#ifdef MODE_LIGHTSOURCE\n"
3137 "       // light source\n"
3138 "#ifdef USEDIFFUSE\n"
3139 "       half3 lightnormal = half3(normalize(LightVector));\n"
3140 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3141 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3142 "#ifdef USESPECULAR\n"
3143 "#ifdef USEEXACTSPECULARMATH\n"
3144 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
3145 "#else\n"
3146 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3147 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
3148 "#endif\n"
3149 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3150 "#endif\n"
3151 "#else\n"
3152 "       color.rgb = diffusetex * Color_Ambient;\n"
3153 "#endif\n"
3154 "       color.rgb *= LightColor;\n"
3155 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
3156 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
3157 "       color.rgb *= ShadowMapCompare(CubeVector,\n"
3158 "# if defined(USESHADOWMAP2D)\n"
3159 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3160 "# endif\n"
3161 "# if defined(USESHADOWMAPRECT)\n"
3162 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3163 "# endif\n"
3164 "# if defined(USESHADOWMAPCUBE)\n"
3165 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
3166 "# endif\n"
3167 "\n"
3168 "#ifdef USESHADOWMAPVSDCT\n"
3169 ", Texture_CubeProjection\n"
3170 "#endif\n"
3171 "       );\n"
3172 "\n"
3173 "#endif\n"
3174 "# ifdef USECUBEFILTER\n"
3175 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector));\n"
3176 "# endif\n"
3177 "#endif // MODE_LIGHTSOURCE\n"
3178 "\n"
3179 "\n"
3180 "\n"
3181 "\n"
3182 "#ifdef MODE_LIGHTDIRECTION\n"
3183 "#define SHADING\n"
3184 "#ifdef USEDIFFUSE\n"
3185 "       half3 lightnormal = half3(normalize(LightVector));\n"
3186 "#endif\n"
3187 "#define lightcolor LightColor\n"
3188 "#endif // MODE_LIGHTDIRECTION\n"
3189 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3190 "#define SHADING\n"
3191 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3192 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3193 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3194 "       // convert modelspace light vector to tangentspace\n"
3195 "       half3 lightnormal;\n"
3196 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3197 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3198 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3199 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3200 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3201 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3202 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3203 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3204 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3205 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3206 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3207 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3208 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3209 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3210 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3211 "#define SHADING\n"
3212 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3213 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3214 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3215 "#endif\n"
3216 "\n"
3217 "\n"
3218 "\n"
3219 "\n"
3220 "#ifdef MODE_LIGHTMAP\n"
3221 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
3222 "#endif // MODE_LIGHTMAP\n"
3223 "#ifdef MODE_VERTEXCOLOR\n"
3224 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3225 "#endif // MODE_VERTEXCOLOR\n"
3226 "#ifdef MODE_FLATCOLOR\n"
3227 "       color.rgb = diffusetex * Color_Ambient;\n"
3228 "#endif // MODE_FLATCOLOR\n"
3229 "\n"
3230 "\n"
3231 "\n"
3232 "\n"
3233 "#ifdef SHADING\n"
3234 "# ifdef USEDIFFUSE\n"
3235 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3236 "#  ifdef USESPECULAR\n"
3237 "#   ifdef USEEXACTSPECULARMATH\n"
3238 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
3239 "#   else\n"
3240 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3241 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
3242 "#   endif\n"
3243 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3244 "#  else\n"
3245 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3246 "#  endif\n"
3247 "# else\n"
3248 "       color.rgb = diffusetex * Color_Ambient;\n"
3249 "# endif\n"
3250 "#endif\n"
3251 "\n"
3252 "#ifdef USESHADOWMAPORTHO\n"
3253 "       color.rgb *= ShadowMapCompare(ShadowMapTC,\n"
3254 "# if defined(USESHADOWMAP2D)\n"
3255 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3256 "# endif\n"
3257 "# if defined(USESHADOWMAPRECT)\n"
3258 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3259 "# endif\n"
3260 "       );\n"
3261 "#endif\n"
3262 "\n"
3263 "#ifdef USEDEFERREDLIGHTMAP\n"
3264 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3265 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
3266 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
3267 "#endif\n"
3268 "\n"
3269 "#ifdef USEGLOW\n"
3270 "#ifdef USEVERTEXTEXTUREBLEND\n"
3271 "       color.rgb += lerp(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
3272 "#else\n"
3273 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
3274 "#endif\n"
3275 "#endif\n"
3276 "\n"
3277 "#ifdef USEFOG\n"
3278 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3279 "#endif\n"
3280 "\n"
3281 "       // 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"
3282 "#ifdef USEREFLECTION\n"
3283 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3284 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3285 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3286 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
3287 "       // FIXME temporary hack to detect the case that the reflection\n"
3288 "       // gets blackened at edges due to leaving the area that contains actual\n"
3289 "       // content.\n"
3290 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3291 "       // 'appening.\n"
3292 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3293 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3294 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3295 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3296 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3297 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
3298 "#endif\n"
3299 "\n"
3300 "       gl_FragColor = float4(color);\n"
3301 "}\n"
3302 "#endif // FRAGMENT_SHADER\n"
3303 "\n"
3304 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3305 "#endif // !MODE_DEFERREDGEOMETRY\n"
3306 "#endif // !MODE_WATER\n"
3307 "#endif // !MODE_REFRACTION\n"
3308 "#endif // !MODE_BLOOMBLUR\n"
3309 "#endif // !MODE_GENERIC\n"
3310 "#endif // !MODE_POSTPROCESS\n"
3311 "#endif // !MODE_SHOWDEPTH\n"
3312 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3313 ;
3314
3315 char *glslshaderstring = NULL;
3316 char *cgshaderstring = NULL;
3317
3318 //=======================================================================================================================================================
3319
3320 typedef struct shaderpermutationinfo_s
3321 {
3322         const char *pretext;
3323         const char *name;
3324 }
3325 shaderpermutationinfo_t;
3326
3327 typedef struct shadermodeinfo_s
3328 {
3329         const char *vertexfilename;
3330         const char *geometryfilename;
3331         const char *fragmentfilename;
3332         const char *pretext;
3333         const char *name;
3334 }
3335 shadermodeinfo_t;
3336
3337 typedef enum shaderpermutation_e
3338 {
3339         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3340         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3341         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3342         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3343         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3344         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3345         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3346         SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3347         SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3348         SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3349         SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3350         SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3351         SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3352         SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3353         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<14, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3354         SHADERPERMUTATION_REFLECTION = 1<<15, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3355         SHADERPERMUTATION_OFFSETMAPPING = 1<<16, ///< adjust texcoords to roughly simulate a displacement mapped surface
3356         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<17, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3357         SHADERPERMUTATION_SHADOWMAPRECT = 1<<18, ///< (lightsource) use shadowmap rectangle texture as light filter
3358         SHADERPERMUTATION_SHADOWMAPCUBE = 1<<19, ///< (lightsource) use shadowmap cubemap texture as light filter
3359         SHADERPERMUTATION_SHADOWMAP2D = 1<<20, ///< (lightsource) use shadowmap rectangle texture as light filter
3360         SHADERPERMUTATION_SHADOWMAPPCF = 1<<21, ///< (lightsource) use percentage closer filtering on shadowmap test results
3361         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<22, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3362         SHADERPERMUTATION_SHADOWSAMPLER = 1<<23, ///< (lightsource) use hardware shadowmap test
3363         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<24, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3364         SHADERPERMUTATION_SHADOWMAPORTHO = 1<<25, //< (lightsource) use orthographic shadowmap projection
3365         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<26, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3366         SHADERPERMUTATION_ALPHAKILL = 1<<27, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3367         SHADERPERMUTATION_REFLECTCUBE = 1<<28, ///< fake reflections using global cubemap (not HDRI light probe)
3368         SHADERPERMUTATION_LIMIT = 1<<29, ///< size of permutations array
3369         SHADERPERMUTATION_COUNT = 29 ///< size of shaderpermutationinfo array
3370 }
3371 shaderpermutation_t;
3372
3373 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3374 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3375 {
3376         {"#define USEDIFFUSE\n", " diffuse"},
3377         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3378         {"#define USEVIEWTINT\n", " viewtint"},
3379         {"#define USECOLORMAPPING\n", " colormapping"},
3380         {"#define USESATURATION\n", " saturation"},
3381         {"#define USEFOGINSIDE\n", " foginside"},
3382         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3383         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3384         {"#define USEGAMMARAMPS\n", " gammaramps"},
3385         {"#define USECUBEFILTER\n", " cubefilter"},
3386         {"#define USEGLOW\n", " glow"},
3387         {"#define USEBLOOM\n", " bloom"},
3388         {"#define USESPECULAR\n", " specular"},
3389         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3390         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3391         {"#define USEREFLECTION\n", " reflection"},
3392         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3393         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3394         {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3395         {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3396         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3397         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3398         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3399         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3400         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3401         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3402         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3403         {"#define USEALPHAKILL\n", " alphakill"},
3404         {"#define USEREFLECTCUBE\n", " reflectcube"},
3405 };
3406
3407 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3408 typedef enum shadermode_e
3409 {
3410         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3411         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3412         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3413         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3414         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3415         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3416         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3417         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3418         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3419         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3420         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3421         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3422         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3423         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3424         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3425         SHADERMODE_COUNT
3426 }
3427 shadermode_t;
3428
3429 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3430 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3431 {
3432         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3433         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3434         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3435         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3436         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3437         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3438         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3439         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3440         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3441         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3442         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3443         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3444         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3445         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3446         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3447 };
3448
3449 #ifdef SUPPORTCG
3450 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3451 {
3452         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3453         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3454         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3455         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3456         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3457         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3458         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3459         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3460         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3461         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3462         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3463         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3464         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3465         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3466         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3467 };
3468 #endif
3469
3470 struct r_glsl_permutation_s;
3471 typedef struct r_glsl_permutation_s
3472 {
3473         /// hash lookup data
3474         struct r_glsl_permutation_s *hashnext;
3475         unsigned int mode;
3476         unsigned int permutation;
3477
3478         /// indicates if we have tried compiling this permutation already
3479         qboolean compiled;
3480         /// 0 if compilation failed
3481         int program;
3482         /// locations of detected uniforms in program object, or -1 if not found
3483         int loc_Texture_First;
3484         int loc_Texture_Second;
3485         int loc_Texture_GammaRamps;
3486         int loc_Texture_Normal;
3487         int loc_Texture_Color;
3488         int loc_Texture_Gloss;
3489         int loc_Texture_Glow;
3490         int loc_Texture_SecondaryNormal;
3491         int loc_Texture_SecondaryColor;
3492         int loc_Texture_SecondaryGloss;
3493         int loc_Texture_SecondaryGlow;
3494         int loc_Texture_Pants;
3495         int loc_Texture_Shirt;
3496         int loc_Texture_FogHeightTexture;
3497         int loc_Texture_FogMask;
3498         int loc_Texture_Lightmap;
3499         int loc_Texture_Deluxemap;
3500         int loc_Texture_Attenuation;
3501         int loc_Texture_Cube;
3502         int loc_Texture_Refraction;
3503         int loc_Texture_Reflection;
3504         int loc_Texture_ShadowMapRect;
3505         int loc_Texture_ShadowMapCube;
3506         int loc_Texture_ShadowMap2D;
3507         int loc_Texture_CubeProjection;
3508         int loc_Texture_ScreenDepth;
3509         int loc_Texture_ScreenNormalMap;
3510         int loc_Texture_ScreenDiffuse;
3511         int loc_Texture_ScreenSpecular;
3512         int loc_Texture_ReflectMask;
3513         int loc_Texture_ReflectCube;
3514         int loc_Alpha;
3515         int loc_BloomBlur_Parameters;
3516         int loc_ClientTime;
3517         int loc_Color_Ambient;
3518         int loc_Color_Diffuse;
3519         int loc_Color_Specular;
3520         int loc_Color_Glow;
3521         int loc_Color_Pants;
3522         int loc_Color_Shirt;
3523         int loc_DeferredColor_Ambient;
3524         int loc_DeferredColor_Diffuse;
3525         int loc_DeferredColor_Specular;
3526         int loc_DeferredMod_Diffuse;
3527         int loc_DeferredMod_Specular;
3528         int loc_DistortScaleRefractReflect;
3529         int loc_EyePosition;
3530         int loc_FogColor;
3531         int loc_FogHeightFade;
3532         int loc_FogPlane;
3533         int loc_FogPlaneViewDist;
3534         int loc_FogRangeRecip;
3535         int loc_LightColor;
3536         int loc_LightDir;
3537         int loc_LightPosition;
3538         int loc_OffsetMapping_Scale;
3539         int loc_PixelSize;
3540         int loc_ReflectColor;
3541         int loc_ReflectFactor;
3542         int loc_ReflectOffset;
3543         int loc_RefractColor;
3544         int loc_Saturation;
3545         int loc_ScreenCenterRefractReflect;
3546         int loc_ScreenScaleRefractReflect;
3547         int loc_ScreenToDepth;
3548         int loc_ShadowMap_Parameters;
3549         int loc_ShadowMap_TextureScale;
3550         int loc_SpecularPower;
3551         int loc_UserVec1;
3552         int loc_UserVec2;
3553         int loc_UserVec3;
3554         int loc_UserVec4;
3555 //      int loc_UseSobel;
3556         int loc_ViewTintColor;
3557         int loc_ViewToLight;
3558         int loc_ModelToLight;
3559         int loc_TexMatrix;
3560         int loc_BackgroundTexMatrix;
3561         int loc_ModelViewProjectionMatrix;
3562         int loc_ModelViewMatrix;
3563         int loc_PixelToScreenTexCoord;
3564         int loc_ModelToReflectCube;
3565         int loc_ShadowMapMatrix;        
3566 }
3567 r_glsl_permutation_t;
3568
3569 #define SHADERPERMUTATION_HASHSIZE 256
3570
3571 /// information about each possible shader permutation
3572 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3573 /// currently selected permutation
3574 r_glsl_permutation_t *r_glsl_permutation;
3575 /// storage for permutations linked in the hash table
3576 memexpandablearray_t r_glsl_permutationarray;
3577
3578 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3579 {
3580         //unsigned int hashdepth = 0;
3581         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3582         r_glsl_permutation_t *p;
3583         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3584         {
3585                 if (p->mode == mode && p->permutation == permutation)
3586                 {
3587                         //if (hashdepth > 10)
3588                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3589                         return p;
3590                 }
3591                 //hashdepth++;
3592         }
3593         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3594         p->mode = mode;
3595         p->permutation = permutation;
3596         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3597         r_glsl_permutationhash[mode][hashindex] = p;
3598         //if (hashdepth > 10)
3599         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3600         return p;
3601 }
3602
3603 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3604 {
3605         char *shaderstring;
3606         if (!filename || !filename[0])
3607                 return NULL;
3608         if (!strcmp(filename, "glsl/default.glsl"))
3609         {
3610                 if (!glslshaderstring)
3611                 {
3612                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3613                         if (glslshaderstring)
3614                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3615                         else
3616                                 glslshaderstring = (char *)builtinshaderstring;
3617                 }
3618                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3619                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3620                 return shaderstring;
3621         }
3622         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3623         if (shaderstring)
3624         {
3625                 if (printfromdisknotice)
3626                         Con_DPrintf("from disk %s... ", filename);
3627                 return shaderstring;
3628         }
3629         return shaderstring;
3630 }
3631
3632 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3633 {
3634         int i;
3635         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3636         int vertstrings_count = 0;
3637         int geomstrings_count = 0;
3638         int fragstrings_count = 0;
3639         char *vertexstring, *geometrystring, *fragmentstring;
3640         const char *vertstrings_list[32+3];
3641         const char *geomstrings_list[32+3];
3642         const char *fragstrings_list[32+3];
3643         char permutationname[256];
3644
3645         if (p->compiled)
3646                 return;
3647         p->compiled = true;
3648         p->program = 0;
3649
3650         permutationname[0] = 0;
3651         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3652         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3653         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3654
3655         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3656
3657         // the first pretext is which type of shader to compile as
3658         // (later these will all be bound together as a program object)
3659         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3660         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3661         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3662
3663         // the second pretext is the mode (for example a light source)
3664         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3665         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3666         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3667         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3668
3669         // now add all the permutation pretexts
3670         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3671         {
3672                 if (permutation & (1<<i))
3673                 {
3674                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3675                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3676                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3677                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3678                 }
3679                 else
3680                 {
3681                         // keep line numbers correct
3682                         vertstrings_list[vertstrings_count++] = "\n";
3683                         geomstrings_list[geomstrings_count++] = "\n";
3684                         fragstrings_list[fragstrings_count++] = "\n";
3685                 }
3686         }
3687
3688         // now append the shader text itself
3689         vertstrings_list[vertstrings_count++] = vertexstring;
3690         geomstrings_list[geomstrings_count++] = geometrystring;
3691         fragstrings_list[fragstrings_count++] = fragmentstring;
3692
3693         // if any sources were NULL, clear the respective list
3694         if (!vertexstring)
3695                 vertstrings_count = 0;
3696         if (!geometrystring)
3697                 geomstrings_count = 0;
3698         if (!fragmentstring)
3699                 fragstrings_count = 0;
3700
3701         // compile the shader program
3702         if (vertstrings_count + geomstrings_count + fragstrings_count)
3703                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3704         if (p->program)
3705         {
3706                 CHECKGLERROR
3707                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3708                 // look up all the uniform variable names we care about, so we don't
3709                 // have to look them up every time we set them
3710
3711                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3712                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3713                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3714                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3715                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3716                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3717                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3718                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3719                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3720                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3721                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3722                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3723                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3724                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3725                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3726                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3727                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3728                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3729                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3730                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3731                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3732                 p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3733                 p->loc_Texture_ShadowMapCube      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3734                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3735                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3736                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3737                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3738                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3739                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3740                 p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3741                 p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3742                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3743                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3744                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3745                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3746                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3747                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3748                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3749                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3750                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3751                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3752                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3753                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3754                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3755                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3756                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3757                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3758                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3759                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3760                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3761                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3762                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3763                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3764                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3765                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3766                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3767                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3768                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3769                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3770                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3771                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3772                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3773                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3774                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3775                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3776                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3777                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3778                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3779                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3780                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3781                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3782                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3783 //              p->loc_UseSobel                   = qglGetUniformLocationARB(p->program, "UseSobel");
3784                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3785                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3786                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3787                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3788                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3789                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3790                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3791                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3792                 p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3793                 p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");            
3794                 // initialize the samplers to refer to the texture units we use
3795                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3796                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3797                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3798                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3799                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3800                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3801                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3802                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3803                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3804                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3805                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3806                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3807                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3808                 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3809                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3810                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3811                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3812                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3813                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3814                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3815                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3816                 if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT);
3817                 if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
3818                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D);
3819                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3820                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3821                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3822                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3823                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3824                 if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
3825                 if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
3826                 CHECKGLERROR
3827                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3828         }
3829         else
3830                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3831
3832         // free the strings
3833         if (vertexstring)
3834                 Mem_Free(vertexstring);
3835         if (geometrystring)
3836                 Mem_Free(geometrystring);
3837         if (fragmentstring)
3838                 Mem_Free(fragmentstring);
3839 }
3840
3841 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3842 {
3843         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3844         if (r_glsl_permutation != perm)
3845         {
3846                 r_glsl_permutation = perm;
3847                 if (!r_glsl_permutation->program)
3848                 {
3849                         if (!r_glsl_permutation->compiled)
3850                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3851                         if (!r_glsl_permutation->program)
3852                         {
3853                                 // remove features until we find a valid permutation
3854                                 int i;
3855                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3856                                 {
3857                                         // reduce i more quickly whenever it would not remove any bits
3858                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3859                                         if (!(permutation & j))
3860                                                 continue;
3861                                         permutation -= j;
3862                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3863                                         if (!r_glsl_permutation->compiled)
3864                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3865                                         if (r_glsl_permutation->program)
3866                                                 break;
3867                                 }
3868                                 if (i >= SHADERPERMUTATION_COUNT)
3869                                 {
3870                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3871                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3872                                         qglUseProgramObjectARB(0);CHECKGLERROR
3873                                         return; // no bit left to clear, entire mode is broken
3874                                 }
3875                         }
3876                 }
3877                 CHECKGLERROR
3878                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3879         }
3880         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3881         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3882         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3883 }
3884
3885 #ifdef SUPPORTCG
3886 #include <Cg/cgGL.h>
3887 struct r_cg_permutation_s;
3888 typedef struct r_cg_permutation_s
3889 {
3890         /// hash lookup data
3891         struct r_cg_permutation_s *hashnext;
3892         unsigned int mode;
3893         unsigned int permutation;
3894
3895         /// indicates if we have tried compiling this permutation already
3896         qboolean compiled;
3897         /// 0 if compilation failed
3898         CGprogram vprogram;
3899         CGprogram fprogram;
3900         /// locations of detected parameters in programs, or NULL if not found
3901         CGparameter vp_EyePosition;
3902         CGparameter vp_FogPlane;
3903         CGparameter vp_LightDir;
3904         CGparameter vp_LightPosition;
3905         CGparameter vp_ModelToLight;
3906         CGparameter vp_TexMatrix;
3907         CGparameter vp_BackgroundTexMatrix;
3908         CGparameter vp_ModelViewProjectionMatrix;
3909         CGparameter vp_ModelViewMatrix;
3910         CGparameter vp_ShadowMapMatrix;
3911
3912         CGparameter fp_Texture_First;
3913         CGparameter fp_Texture_Second;
3914         CGparameter fp_Texture_GammaRamps;
3915         CGparameter fp_Texture_Normal;
3916         CGparameter fp_Texture_Color;
3917         CGparameter fp_Texture_Gloss;
3918         CGparameter fp_Texture_Glow;
3919         CGparameter fp_Texture_SecondaryNormal;
3920         CGparameter fp_Texture_SecondaryColor;
3921         CGparameter fp_Texture_SecondaryGloss;
3922         CGparameter fp_Texture_SecondaryGlow;
3923         CGparameter fp_Texture_Pants;
3924         CGparameter fp_Texture_Shirt;
3925         CGparameter fp_Texture_FogHeightTexture;
3926         CGparameter fp_Texture_FogMask;
3927         CGparameter fp_Texture_Lightmap;
3928         CGparameter fp_Texture_Deluxemap;
3929         CGparameter fp_Texture_Attenuation;
3930         CGparameter fp_Texture_Cube;
3931         CGparameter fp_Texture_Refraction;
3932         CGparameter fp_Texture_Reflection;
3933         CGparameter fp_Texture_ShadowMapRect;
3934         CGparameter fp_Texture_ShadowMapCube;
3935         CGparameter fp_Texture_ShadowMap2D;
3936         CGparameter fp_Texture_CubeProjection;
3937         CGparameter fp_Texture_ScreenDepth;
3938         CGparameter fp_Texture_ScreenNormalMap;
3939         CGparameter fp_Texture_ScreenDiffuse;
3940         CGparameter fp_Texture_ScreenSpecular;
3941         CGparameter fp_Texture_ReflectMask;
3942         CGparameter fp_Texture_ReflectCube;
3943         CGparameter fp_Alpha;
3944         CGparameter fp_BloomBlur_Parameters;
3945         CGparameter fp_ClientTime;
3946         CGparameter fp_Color_Ambient;
3947         CGparameter fp_Color_Diffuse;
3948         CGparameter fp_Color_Specular;
3949         CGparameter fp_Color_Glow;
3950         CGparameter fp_Color_Pants;
3951         CGparameter fp_Color_Shirt;
3952         CGparameter fp_DeferredColor_Ambient;
3953         CGparameter fp_DeferredColor_Diffuse;
3954         CGparameter fp_DeferredColor_Specular;
3955         CGparameter fp_DeferredMod_Diffuse;
3956         CGparameter fp_DeferredMod_Specular;
3957         CGparameter fp_DistortScaleRefractReflect;
3958         CGparameter fp_EyePosition;
3959         CGparameter fp_FogColor;
3960         CGparameter fp_FogHeightFade;
3961         CGparameter fp_FogPlane;
3962         CGparameter fp_FogPlaneViewDist;
3963         CGparameter fp_FogRangeRecip;
3964         CGparameter fp_LightColor;
3965         CGparameter fp_LightDir;
3966         CGparameter fp_LightPosition;
3967         CGparameter fp_OffsetMapping_Scale;
3968         CGparameter fp_PixelSize;
3969         CGparameter fp_ReflectColor;
3970         CGparameter fp_ReflectFactor;
3971         CGparameter fp_ReflectOffset;
3972         CGparameter fp_RefractColor;
3973         CGparameter fp_Saturation;
3974         CGparameter fp_ScreenCenterRefractReflect;
3975         CGparameter fp_ScreenScaleRefractReflect;
3976         CGparameter fp_ScreenToDepth;
3977         CGparameter fp_ShadowMap_Parameters;
3978         CGparameter fp_ShadowMap_TextureScale;
3979         CGparameter fp_SpecularPower;
3980         CGparameter fp_UserVec1;
3981         CGparameter fp_UserVec2;
3982         CGparameter fp_UserVec3;
3983         CGparameter fp_UserVec4;
3984         CGparameter fp_ViewTintColor;
3985         CGparameter fp_ViewToLight;
3986         CGparameter fp_PixelToScreenTexCoord;
3987         CGparameter fp_ModelToReflectCube;
3988 }
3989 r_cg_permutation_t;
3990
3991 /// information about each possible shader permutation
3992 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3993 /// currently selected permutation
3994 r_cg_permutation_t *r_cg_permutation;
3995 /// storage for permutations linked in the hash table
3996 memexpandablearray_t r_cg_permutationarray;
3997
3998 #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));}}
3999
4000 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
4001 {
4002         //unsigned int hashdepth = 0;
4003         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4004         r_cg_permutation_t *p;
4005         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
4006         {
4007                 if (p->mode == mode && p->permutation == permutation)
4008                 {
4009                         //if (hashdepth > 10)
4010                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4011                         return p;
4012                 }
4013                 //hashdepth++;
4014         }
4015         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
4016         p->mode = mode;
4017         p->permutation = permutation;
4018         p->hashnext = r_cg_permutationhash[mode][hashindex];
4019         r_cg_permutationhash[mode][hashindex] = p;
4020         //if (hashdepth > 10)
4021         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4022         return p;
4023 }
4024
4025 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
4026 {
4027         char *shaderstring;
4028         if (!filename || !filename[0])
4029                 return NULL;
4030         if (!strcmp(filename, "cg/default.cg"))
4031         {
4032                 if (!cgshaderstring)
4033                 {
4034                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4035                         if (cgshaderstring)
4036                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4037                         else
4038                                 cgshaderstring = (char *)builtincgshaderstring;
4039                 }
4040                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4041                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4042                 return shaderstring;
4043         }
4044         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4045         if (shaderstring)
4046         {
4047                 if (printfromdisknotice)
4048                         Con_DPrintf("from disk %s... ", filename);
4049                 return shaderstring;
4050         }
4051         return shaderstring;
4052 }
4053
4054 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4055 {
4056         // TODO: load or create .fp and .vp shader files
4057 }
4058
4059 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4060 {
4061         int i;
4062         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4063         int vertstrings_count = 0, vertstring_length = 0;
4064         int geomstrings_count = 0, geomstring_length = 0;
4065         int fragstrings_count = 0, fragstring_length = 0;
4066         char *t;
4067         char *vertexstring, *geometrystring, *fragmentstring;
4068         char *vertstring, *geomstring, *fragstring;
4069         const char *vertstrings_list[32+3];
4070         const char *geomstrings_list[32+3];
4071         const char *fragstrings_list[32+3];
4072         char permutationname[256];
4073         char cachename[256];
4074         CGprofile vertexProfile;
4075         CGprofile fragmentProfile;
4076
4077         if (p->compiled)
4078                 return;
4079         p->compiled = true;
4080         p->vprogram = NULL;
4081         p->fprogram = NULL;
4082
4083         permutationname[0] = 0;
4084         cachename[0] = 0;
4085         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
4086         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4087         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4088
4089         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4090         strlcat(cachename, "cg/", sizeof(cachename));
4091
4092         // the first pretext is which type of shader to compile as
4093         // (later these will all be bound together as a program object)
4094         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4095         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4096         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4097
4098         // the second pretext is the mode (for example a light source)
4099         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4100         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4101         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4102         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4103         strlcat(cachename, modeinfo->name, sizeof(cachename));
4104
4105         // now add all the permutation pretexts
4106         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4107         {
4108                 if (permutation & (1<<i))
4109                 {
4110                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4111                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4112                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4113                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4114                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4115                 }
4116                 else
4117                 {
4118                         // keep line numbers correct
4119                         vertstrings_list[vertstrings_count++] = "\n";
4120                         geomstrings_list[geomstrings_count++] = "\n";
4121                         fragstrings_list[fragstrings_count++] = "\n";
4122                 }
4123         }
4124
4125         // replace spaces in the cachename with _ characters
4126         for (i = 0;cachename[i];i++)
4127                 if (cachename[i] == ' ')
4128                         cachename[i] = '_';
4129
4130         // now append the shader text itself
4131         vertstrings_list[vertstrings_count++] = vertexstring;
4132         geomstrings_list[geomstrings_count++] = geometrystring;
4133         fragstrings_list[fragstrings_count++] = fragmentstring;
4134
4135         // if any sources were NULL, clear the respective list
4136         if (!vertexstring)
4137                 vertstrings_count = 0;
4138         if (!geometrystring)
4139                 geomstrings_count = 0;
4140         if (!fragmentstring)
4141                 fragstrings_count = 0;
4142
4143         vertstring_length = 0;
4144         for (i = 0;i < vertstrings_count;i++)
4145                 vertstring_length += strlen(vertstrings_list[i]);
4146         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4147         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4148                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4149
4150         geomstring_length = 0;
4151         for (i = 0;i < geomstrings_count;i++)
4152                 geomstring_length += strlen(geomstrings_list[i]);
4153         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4154         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4155                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4156
4157         fragstring_length = 0;
4158         for (i = 0;i < fragstrings_count;i++)
4159                 fragstring_length += strlen(fragstrings_list[i]);
4160         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4161         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4162                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4163
4164         CHECKGLERROR
4165         CHECKCGERROR
4166         //vertexProfile = CG_PROFILE_ARBVP1;
4167         //fragmentProfile = CG_PROFILE_ARBFP1;
4168         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4169         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4170         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4171         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4172         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4173         CHECKGLERROR
4174
4175         // try to load the cached shader, or generate one
4176         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4177
4178         // if caching failed, do a dynamic compile for now
4179         CHECKCGERROR
4180         if (vertstring[0] && !p->vprogram)
4181                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4182         CHECKCGERROR
4183         if (fragstring[0] && !p->fprogram)
4184                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4185         CHECKCGERROR
4186
4187         // look up all the uniform variable names we care about, so we don't
4188         // have to look them up every time we set them
4189         if (p->vprogram)
4190         {
4191                 CHECKCGERROR
4192                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4193                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4194                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4195                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4196                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4197                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4198                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4199                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4200                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4201                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4202                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4203                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4204                 CHECKCGERROR
4205         }
4206         if (p->fprogram)
4207         {
4208                 CHECKCGERROR
4209                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4210                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4211                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4212                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4213                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4214                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4215                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4216                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4217                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4218                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4219                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4220                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4221                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4222                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4223                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4224                 p->fp_Texture_FogHeightTexture   = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4225                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4226                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4227                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4228                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4229                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4230                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4231                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4232                 p->fp_Texture_ShadowMapRect      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
4233                 p->fp_Texture_ShadowMapCube      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
4234                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4235                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4236                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4237                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4238                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4239                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4240                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4241                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4242                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4243                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4244                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4245                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4246                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4247                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4248                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4249                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4250                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4251                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4252                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4253                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4254                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4255                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4256                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4257                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4258                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4259                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4260                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4261                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4262                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4263                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4264                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4265                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4266                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4267                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4268                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4269                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4270                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4271                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4272                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4273                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4274                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4275                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4276                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4277                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4278                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4279                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4280                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4281                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4282                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4283 //              p->fp_UseSobel                   = cgGetNamedParameter(p->fprogram, "UseSobel");
4284                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4285                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4286                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4287                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4288                 CHECKCGERROR
4289         }
4290
4291         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4292                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4293         else
4294                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4295
4296         // free the strings
4297         if (vertstring)
4298                 Mem_Free(vertstring);
4299         if (geomstring)
4300                 Mem_Free(geomstring);
4301         if (fragstring)
4302                 Mem_Free(fragstring);
4303         if (vertexstring)
4304                 Mem_Free(vertexstring);
4305         if (geometrystring)
4306                 Mem_Free(geometrystring);
4307         if (fragmentstring)
4308                 Mem_Free(fragmentstring);
4309 }
4310
4311 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4312 {
4313         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4314         CHECKGLERROR
4315         CHECKCGERROR
4316         if (r_cg_permutation != perm)
4317         {
4318                 r_cg_permutation = perm;
4319                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4320                 {
4321                         if (!r_cg_permutation->compiled)
4322                                 R_CG_CompilePermutation(perm, mode, permutation);
4323                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4324                         {
4325                                 // remove features until we find a valid permutation
4326                                 int i;
4327                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4328                                 {
4329                                         // reduce i more quickly whenever it would not remove any bits
4330                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4331                                         if (!(permutation & j))
4332                                                 continue;
4333                                         permutation -= j;
4334                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4335                                         if (!r_cg_permutation->compiled)
4336                                                 R_CG_CompilePermutation(perm, mode, permutation);
4337                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4338                                                 break;
4339                                 }
4340                                 if (i >= SHADERPERMUTATION_COUNT)
4341                                 {
4342                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4343                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4344                                         return; // no bit left to clear, entire mode is broken
4345                                 }
4346                         }
4347                 }
4348                 CHECKGLERROR
4349                 CHECKCGERROR
4350                 if (r_cg_permutation->vprogram)
4351                 {
4352                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4353                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4354                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4355                 }
4356                 else
4357                 {
4358                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4359                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4360                 }
4361                 if (r_cg_permutation->fprogram)
4362                 {
4363                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4364                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4365                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4366                 }
4367                 else
4368                 {
4369                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4370                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4371                 }
4372         }
4373         CHECKCGERROR
4374         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4375         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4376         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4377 }
4378
4379 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4380 {
4381         cgGLSetTextureParameter(param, R_GetTexture(tex));
4382         cgGLEnableTextureParameter(param);
4383 }
4384 #endif
4385
4386 void R_GLSL_Restart_f(void)
4387 {
4388         unsigned int i, limit;
4389         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4390                 Mem_Free(glslshaderstring);
4391         glslshaderstring = NULL;
4392         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4393                 Mem_Free(cgshaderstring);
4394         cgshaderstring = NULL;
4395         switch(vid.renderpath)
4396         {
4397         case RENDERPATH_GL20:
4398                 {
4399                         r_glsl_permutation_t *p;
4400                         r_glsl_permutation = NULL;
4401                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4402                         for (i = 0;i < limit;i++)
4403                         {
4404                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4405                                 {
4406                                         GL_Backend_FreeProgram(p->program);
4407                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4408                                 }
4409                         }
4410                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4411                 }
4412                 break;
4413         case RENDERPATH_CGGL:
4414 #ifdef SUPPORTCG
4415                 {
4416                         r_cg_permutation_t *p;
4417                         r_cg_permutation = NULL;
4418                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4419                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4420                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4421                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4422                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4423                         for (i = 0;i < limit;i++)
4424                         {
4425                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4426                                 {
4427                                         if (p->vprogram)
4428                                                 cgDestroyProgram(p->vprogram);
4429                                         if (p->fprogram)
4430                                                 cgDestroyProgram(p->fprogram);
4431                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4432                                 }
4433                         }
4434                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4435                 }
4436                 break;
4437 #endif
4438         case RENDERPATH_GL13:
4439         case RENDERPATH_GL11:
4440                 break;
4441         }
4442 }
4443
4444 void R_GLSL_DumpShader_f(void)
4445 {
4446         int i;
4447         qfile_t *file;
4448
4449         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4450         if (file)
4451         {
4452                 FS_Print(file, "/* The engine may define the following macros:\n");
4453                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4454                 for (i = 0;i < SHADERMODE_COUNT;i++)
4455                         FS_Print(file, glslshadermodeinfo[i].pretext);
4456                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4457                         FS_Print(file, shaderpermutationinfo[i].pretext);
4458                 FS_Print(file, "*/\n");
4459                 FS_Print(file, builtinshaderstring);
4460                 FS_Close(file);
4461                 Con_Printf("glsl/default.glsl written\n");
4462         }
4463         else
4464                 Con_Printf("failed to write to glsl/default.glsl\n");
4465
4466 #ifdef SUPPORTCG
4467         file = FS_OpenRealFile("cg/default.cg", "w", false);
4468         if (file)
4469         {
4470                 FS_Print(file, "/* The engine may define the following macros:\n");
4471                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4472                 for (i = 0;i < SHADERMODE_COUNT;i++)
4473                         FS_Print(file, cgshadermodeinfo[i].pretext);
4474                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4475                         FS_Print(file, shaderpermutationinfo[i].pretext);
4476                 FS_Print(file, "*/\n");
4477                 FS_Print(file, builtincgshaderstring);
4478                 FS_Close(file);
4479                 Con_Printf("cg/default.cg written\n");
4480         }
4481         else
4482                 Con_Printf("failed to write to cg/default.cg\n");
4483 #endif
4484 }
4485
4486 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4487 {
4488         if (!second)
4489                 texturemode = GL_MODULATE;
4490         switch (vid.renderpath)
4491         {
4492         case RENDERPATH_GL20:
4493                 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))));
4494                 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
4495                 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, second);
4496                 break;
4497         case RENDERPATH_CGGL:
4498 #ifdef SUPPORTCG
4499                 CHECKCGERROR
4500                 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))));
4501                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4502                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4503 #endif
4504                 break;
4505         case RENDERPATH_GL13:
4506                 R_Mesh_TexBind(0, first );
4507                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4508                 R_Mesh_TexBind(1, second);
4509                 if (second)
4510                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4511                 break;
4512         case RENDERPATH_GL11:
4513                 R_Mesh_TexBind(0, first );
4514                 break;
4515         }
4516 }
4517
4518 void R_SetupShader_DepthOrShadow(void)
4519 {
4520         switch (vid.renderpath)
4521         {
4522         case RENDERPATH_GL20:
4523                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4524                 break;
4525         case RENDERPATH_CGGL:
4526 #ifdef SUPPORTCG
4527                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4528 #endif
4529                 break;
4530         case RENDERPATH_GL13:
4531                 R_Mesh_TexBind(0, 0);
4532                 R_Mesh_TexBind(1, 0);
4533                 break;
4534         case RENDERPATH_GL11:
4535                 R_Mesh_TexBind(0, 0);
4536                 break;
4537         }
4538 }
4539
4540 void R_SetupShader_ShowDepth(void)
4541 {
4542         switch (vid.renderpath)
4543         {
4544         case RENDERPATH_GL20:
4545                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4546                 break;
4547         case RENDERPATH_CGGL:
4548 #ifdef SUPPORTCG
4549                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4550 #endif
4551                 break;
4552         case RENDERPATH_GL13:
4553                 break;
4554         case RENDERPATH_GL11:
4555                 break;
4556         }
4557 }
4558
4559 extern qboolean r_shadow_usingdeferredprepass;
4560 extern cvar_t r_shadow_deferred_8bitrange;
4561 extern rtexture_t *r_shadow_attenuationgradienttexture;
4562 extern rtexture_t *r_shadow_attenuation2dtexture;
4563 extern rtexture_t *r_shadow_attenuation3dtexture;
4564 extern qboolean r_shadow_usingshadowmaprect;
4565 extern qboolean r_shadow_usingshadowmapcube;
4566 extern qboolean r_shadow_usingshadowmap2d;
4567 extern qboolean r_shadow_usingshadowmaportho;
4568 extern float r_shadow_shadowmap_texturescale[2];
4569 extern float r_shadow_shadowmap_parameters[4];
4570 extern qboolean r_shadow_shadowmapvsdct;
4571 extern qboolean r_shadow_shadowmapsampler;
4572 extern int r_shadow_shadowmappcf;
4573 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4574 extern rtexture_t *r_shadow_shadowmap2dtexture;
4575 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4576 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4577 extern matrix4x4_t r_shadow_shadowmapmatrix;
4578 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4579 extern int r_shadow_prepass_width;
4580 extern int r_shadow_prepass_height;
4581 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4582 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4583 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4584 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4585 extern cvar_t gl_mesh_separatearrays;
4586 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist)
4587 {
4588         // select a permutation of the lighting shader appropriate to this
4589         // combination of texture, entity, light source, and fogging, only use the
4590         // minimum features necessary to avoid wasting rendering time in the
4591         // fragment shader on features that are not being used
4592         unsigned int permutation = 0;
4593         unsigned int mode = 0;
4594         float m16f[16];
4595         if (rsurfacepass == RSURFPASS_BACKGROUND)
4596         {
4597                 // distorted background
4598                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4599                         mode = SHADERMODE_WATER;
4600                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
4601                         mode = SHADERMODE_REFRACTION;
4602                 else
4603                 {
4604                         mode = SHADERMODE_GENERIC;
4605                         permutation |= SHADERPERMUTATION_DIFFUSE;
4606                 }
4607                 GL_AlphaTest(false);
4608                 GL_BlendFunc(GL_ONE, GL_ZERO);
4609         }
4610         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4611         {
4612                 if (r_glsl_offsetmapping.integer)
4613                 {
4614                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4615                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4616                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4617                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4618                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4619                         {
4620                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4621                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4622                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4623                         }
4624                 }
4625                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4626                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4627                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4628                         permutation |= SHADERPERMUTATION_ALPHAKILL;
4629                 // normalmap (deferred prepass), may use alpha test on diffuse
4630                 mode = SHADERMODE_DEFERREDGEOMETRY;
4631                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4632                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4633                 GL_AlphaTest(false);
4634                 GL_BlendFunc(GL_ONE, GL_ZERO);
4635         }
4636         else if (rsurfacepass == RSURFPASS_RTLIGHT)
4637         {
4638                 if (r_glsl_offsetmapping.integer)
4639                 {
4640                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4641                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4642                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4643                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4644                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4645                         {
4646                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4647                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4648                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4649                         }
4650                 }
4651                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4652                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4653                 // light source
4654                 mode = SHADERMODE_LIGHTSOURCE;
4655                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4656                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4657                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4658                         permutation |= SHADERPERMUTATION_CUBEFILTER;
4659                 if (diffusescale > 0)
4660                         permutation |= SHADERPERMUTATION_DIFFUSE;
4661                 if (specularscale > 0)
4662                 {
4663                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4664                         if (r_shadow_glossexact.integer)
4665                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4666                 }
4667                 if (r_refdef.fogenabled)
4668                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4669                 if (rsurface.texture->colormapping)
4670                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4671                 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4672                 {
4673                         if (r_shadow_usingshadowmaprect)
4674                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4675                         if (r_shadow_usingshadowmap2d)
4676                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4677                         if (r_shadow_usingshadowmapcube)
4678                                 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4679                         else if(r_shadow_shadowmapvsdct)
4680                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4681
4682                         if (r_shadow_shadowmapsampler)
4683                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4684                         if (r_shadow_shadowmappcf > 1)
4685                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4686                         else if (r_shadow_shadowmappcf)
4687                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4688                 }
4689                 if (rsurface.texture->reflectmasktexture)
4690                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4691                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4692                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4693         }
4694         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4695         {
4696                 if (r_glsl_offsetmapping.integer)
4697                 {
4698                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4699                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4700                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4701                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4702                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4703                         {
4704                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4705                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4706                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4707                         }
4708                 }
4709                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4710                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4711                 // unshaded geometry (fullbright or ambient model lighting)
4712                 mode = SHADERMODE_FLATCOLOR;
4713                 ambientscale = diffusescale = specularscale = 0;
4714                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4715                         permutation |= SHADERPERMUTATION_GLOW;
4716                 if (r_refdef.fogenabled)
4717                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4718                 if (rsurface.texture->colormapping)
4719                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4720                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4721                 {
4722                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4723                         if (r_shadow_usingshadowmaprect)
4724                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4725                         if (r_shadow_usingshadowmap2d)
4726                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4727
4728                         if (r_shadow_shadowmapsampler)
4729                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4730                         if (r_shadow_shadowmappcf > 1)
4731                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4732                         else if (r_shadow_shadowmappcf)
4733                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4734                 }
4735                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4736                         permutation |= SHADERPERMUTATION_REFLECTION;
4737                 if (rsurface.texture->reflectmasktexture)
4738                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4739                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4740                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4741         }
4742         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4743         {
4744                 if (r_glsl_offsetmapping.integer)
4745                 {
4746                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4747                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4748                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4749                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4750                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4751                         {
4752                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4753                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4754                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4755                         }
4756                 }
4757                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4758                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4759                 // directional model lighting
4760                 mode = SHADERMODE_LIGHTDIRECTION;
4761                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4762                         permutation |= SHADERPERMUTATION_GLOW;
4763                 permutation |= SHADERPERMUTATION_DIFFUSE;
4764                 if (specularscale > 0)
4765                 {
4766                         permutation |= SHADERPERMUTATION_SPECULAR;
4767                         if (r_shadow_glossexact.integer)
4768                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4769                 }
4770                 if (r_refdef.fogenabled)
4771                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4772                 if (rsurface.texture->colormapping)
4773                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4774                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4775                 {
4776                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4777                         if (r_shadow_usingshadowmaprect)
4778                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4779                         if (r_shadow_usingshadowmap2d)
4780                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4781
4782                         if (r_shadow_shadowmapsampler)
4783                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4784                         if (r_shadow_shadowmappcf > 1)
4785                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4786                         else if (r_shadow_shadowmappcf)
4787                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4788                 }
4789                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4790                         permutation |= SHADERPERMUTATION_REFLECTION;
4791                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4792                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4793                 if (rsurface.texture->reflectmasktexture)
4794                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4795                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4796                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4797         }
4798         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
4799         {
4800                 if (r_glsl_offsetmapping.integer)
4801                 {
4802                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4803                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4804                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4805                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4806                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4807                         {
4808                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4809                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4810                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4811                         }
4812                 }
4813                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4814                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4815                 // ambient model lighting
4816                 mode = SHADERMODE_LIGHTDIRECTION;
4817                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4818                         permutation |= SHADERPERMUTATION_GLOW;
4819                 if (r_refdef.fogenabled)
4820                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4821                 if (rsurface.texture->colormapping)
4822                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4823                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4824                 {
4825                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4826                         if (r_shadow_usingshadowmaprect)
4827                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4828                         if (r_shadow_usingshadowmap2d)
4829                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4830
4831                         if (r_shadow_shadowmapsampler)
4832                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4833                         if (r_shadow_shadowmappcf > 1)
4834                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4835                         else if (r_shadow_shadowmappcf)
4836                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4837                 }
4838                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4839                         permutation |= SHADERPERMUTATION_REFLECTION;
4840                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4841                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4842                 if (rsurface.texture->reflectmasktexture)
4843                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4844                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4845                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4846         }
4847         else
4848         {
4849                 if (r_glsl_offsetmapping.integer)
4850                 {
4851                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4852                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4853                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4854                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4855                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4856                         {
4857                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4858                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4859                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4860                         }
4861                 }
4862                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4863                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4864                 // lightmapped wall
4865                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4866                         permutation |= SHADERPERMUTATION_GLOW;
4867                 if (r_refdef.fogenabled)
4868                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4869                 if (rsurface.texture->colormapping)
4870                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4871                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4872                 {
4873                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4874                         if (r_shadow_usingshadowmaprect)
4875                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4876                         if (r_shadow_usingshadowmap2d)
4877                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4878
4879                         if (r_shadow_shadowmapsampler)
4880                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4881                         if (r_shadow_shadowmappcf > 1)
4882                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4883                         else if (r_shadow_shadowmappcf)
4884                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4885                 }
4886                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4887                         permutation |= SHADERPERMUTATION_REFLECTION;
4888                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4889                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4890                 if (rsurface.texture->reflectmasktexture)
4891                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4892                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
4893                 {
4894                         // deluxemapping (light direction texture)
4895                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
4896                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
4897                         else
4898                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4899                         permutation |= SHADERPERMUTATION_DIFFUSE;
4900                         if (specularscale > 0)
4901                         {
4902                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4903                                 if (r_shadow_glossexact.integer)
4904                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4905                         }
4906                 }
4907                 else if (r_glsl_deluxemapping.integer >= 2)
4908                 {
4909                         // fake deluxemapping (uniform light direction in tangentspace)
4910                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4911                         permutation |= SHADERPERMUTATION_DIFFUSE;
4912                         if (specularscale > 0)
4913                         {
4914                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4915                                 if (r_shadow_glossexact.integer)
4916                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4917                         }
4918                 }
4919                 else if (rsurface.uselightmaptexture)
4920                 {
4921                         // ordinary lightmapping (q1bsp, q3bsp)
4922                         mode = SHADERMODE_LIGHTMAP;
4923                 }
4924                 else
4925                 {
4926                         // ordinary vertex coloring (q3bsp)
4927                         mode = SHADERMODE_VERTEXCOLOR;
4928                 }
4929                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4930                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4931         }
4932         switch(vid.renderpath)
4933         {
4934         case RENDERPATH_GL20:
4935                 if (gl_mesh_separatearrays.integer)
4936                 {
4937                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
4938                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
4939                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
4940                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
4941                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
4942                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
4943                         R_Mesh_TexCoordPointer(3, 4, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
4944                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
4945                 }
4946                 else
4947                 {
4948                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
4949                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
4950                 }
4951                 R_SetupShader_SetPermutationGLSL(mode, permutation);
4952                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
4953                 if (mode == SHADERMODE_LIGHTSOURCE)
4954                 {
4955                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
4956                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
4957                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
4958                         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);
4959                         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);
4960                         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);
4961         
4962                         // additive passes are only darkened by fog, not tinted
4963                         if (r_glsl_permutation->loc_FogColor >= 0)
4964                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4965                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4966                 }
4967                 else
4968                 {
4969                         if (mode == SHADERMODE_FLATCOLOR)
4970                         {
4971                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
4972                         }
4973                         else if (mode == SHADERMODE_LIGHTDIRECTION)
4974                         {
4975                                 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]);
4976                                 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]);
4977                                 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);
4978                                 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);
4979                                 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);
4980                                 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]);
4981                                 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]);
4982                         }
4983                         else
4984                         {
4985                                 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]);
4986                                 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]);
4987                                 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);
4988                                 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);
4989                                 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);
4990                         }
4991                         // additive passes are only darkened by fog, not tinted
4992                         if (r_glsl_permutation->loc_FogColor >= 0)
4993                         {
4994                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4995                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4996                                 else
4997                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4998                         }
4999                         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);
5000                         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]);
5001                         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]);
5002                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
5003                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
5004                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5005                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5006                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5007                 }
5008                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5009                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5010                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5011                 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]);
5012                 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]);
5013
5014                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5015                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
5016                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5017                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5018                 {
5019                         if (rsurface.texture->pantstexture)
5020                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5021                         else
5022                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5023                 }
5024                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5025                 {
5026                         if (rsurface.texture->shirttexture)
5027                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5028                         else
5029                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5030                 }
5031                 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]);
5032                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5033                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5034                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5035                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5036                 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]);
5037                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5038
5039         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
5040         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
5041         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
5042                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5043                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5044                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5045                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5046                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5047                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5048                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5049                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5050                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5051                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5052                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5053                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5054                 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5055                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5056                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_white                                     );
5057                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_blanknormalmap                            );
5058                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5059                 if (r_glsl_permutation->loc_Texture_Refraction      >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , r_texture_white                                     );
5060                 if (r_glsl_permutation->loc_Texture_Reflection      >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , r_texture_white                                     );
5061                 if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5062                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5063                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5064                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5065                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5066                 {
5067                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
5068                         if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT, r_shadow_shadowmaprectangletexture                  );
5069                         if (rsurface.rtlight)
5070                         {
5071                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5072                                 if (r_shadow_usingshadowmapcube)
5073                                         if (r_glsl_permutation->loc_Texture_ShadowMapCube   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE     , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5074                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5075                         }
5076                 }
5077                 CHECKGLERROR
5078                 break;
5079         case RENDERPATH_CGGL:
5080 #ifdef SUPPORTCG
5081                 if (gl_mesh_separatearrays.integer)
5082                 {
5083                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
5084                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5085                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5086                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5087                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5088                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5089                         R_Mesh_TexCoordPointer(3, 4, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5090                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5091                 }
5092                 else
5093                 {
5094                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
5095                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5096                 }
5097                 R_SetupShader_SetPermutationCG(mode, permutation);
5098                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
5099                 if (mode == SHADERMODE_LIGHTSOURCE)
5100                 {
5101                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
5102                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5103                 }
5104                 else
5105                 {
5106                         if (mode == SHADERMODE_LIGHTDIRECTION)
5107                         {
5108                                 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
5109                         }
5110                 }
5111                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
5112                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
5113                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
5114                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5115                 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
5116                 CHECKGLERROR
5117
5118                 if (mode == SHADERMODE_LIGHTSOURCE)
5119                 {
5120                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5121                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
5122                         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
5123                         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
5124                         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
5125
5126                         // additive passes are only darkened by fog, not tinted
5127                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
5128                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5129                 }
5130                 else
5131                 {
5132                         if (mode == SHADERMODE_FLATCOLOR)
5133                         {
5134                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);CHECKCGERROR
5135                         }
5136                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5137                         {
5138                                 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
5139                                 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
5140                                 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
5141                                 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
5142                                 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
5143                                 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
5144                                 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
5145                         }
5146                         else
5147                         {
5148                                 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
5149                                 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
5150                                 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
5151                                 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
5152                                 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
5153                         }
5154                         // additive passes are only darkened by fog, not tinted
5155                         if (r_cg_permutation->fp_FogColor)
5156                         {
5157                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5158                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
5159                                 else
5160                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5161                                 CHECKCGERROR
5162                         }
5163                         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
5164                         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
5165                         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
5166                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
5167                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
5168                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
5169                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
5170                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5171                 }
5172                 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
5173                 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
5174                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
5175                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
5176                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5177                 if (r_cg_permutation->fp_Color_Pants)
5178                 {
5179                         if (rsurface.texture->pantstexture)
5180                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5181                         else
5182                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
5183                         CHECKCGERROR
5184                 }
5185                 if (r_cg_permutation->fp_Color_Shirt)
5186                 {
5187                         if (rsurface.texture->shirttexture)
5188                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5189                         else
5190                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
5191                         CHECKCGERROR
5192                 }
5193                 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
5194                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
5195                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
5196                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
5197                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
5198                 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
5199                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5200
5201         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
5202         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
5203         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
5204                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
5205                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
5206                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
5207                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
5208                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
5209                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
5210                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
5211                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
5212                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
5213                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
5214                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
5215                 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
5216                 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
5217                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
5218                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , r_texture_white                                     );CHECKCGERROR
5219                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , r_texture_blanknormalmap                            );CHECKCGERROR
5220                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
5221                 if (r_cg_permutation->fp_Texture_Refraction     ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction     , r_texture_white                                     );CHECKCGERROR
5222                 if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , r_texture_white                                     );CHECKCGERROR
5223                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
5224                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
5225                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
5226                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
5227                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5228                 {
5229                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5230                         if (r_cg_permutation->fp_Texture_ShadowMapRect  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
5231                         if (rsurface.rtlight)
5232                         {
5233                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
5234                                 if (r_shadow_usingshadowmapcube)
5235                                         if (r_cg_permutation->fp_Texture_ShadowMapCube  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5236                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
5237                         }
5238                 }
5239
5240                 CHECKGLERROR
5241 #endif
5242                 break;
5243         case RENDERPATH_GL13:
5244         case RENDERPATH_GL11:
5245                 break;
5246         }
5247 }
5248
5249 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
5250 {
5251         // select a permutation of the lighting shader appropriate to this
5252         // combination of texture, entity, light source, and fogging, only use the
5253         // minimum features necessary to avoid wasting rendering time in the
5254         // fragment shader on features that are not being used
5255         unsigned int permutation = 0;
5256         unsigned int mode = 0;
5257         const float *lightcolorbase = rtlight->currentcolor;
5258         float ambientscale = rtlight->ambientscale;
5259         float diffusescale = rtlight->diffusescale;
5260         float specularscale = rtlight->specularscale;
5261         // this is the location of the light in view space
5262         vec3_t viewlightorigin;
5263         // this transforms from view space (camera) to light space (cubemap)
5264         matrix4x4_t viewtolight;
5265         matrix4x4_t lighttoview;
5266         float viewtolight16f[16];
5267         float range = 1.0f / r_shadow_deferred_8bitrange.value;
5268         // light source
5269         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
5270         if (rtlight->currentcubemap != r_texture_whitecube)
5271                 permutation |= SHADERPERMUTATION_CUBEFILTER;
5272         if (diffusescale > 0)
5273                 permutation |= SHADERPERMUTATION_DIFFUSE;
5274         if (specularscale > 0)
5275         {
5276                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5277                 if (r_shadow_glossexact.integer)
5278                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5279         }
5280         if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
5281         {
5282                 if (r_shadow_usingshadowmaprect)
5283                         permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5284                 if (r_shadow_usingshadowmap2d)
5285                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5286                 if (r_shadow_usingshadowmapcube)
5287                         permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
5288                 else if(r_shadow_shadowmapvsdct)
5289                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5290
5291                 if (r_shadow_shadowmapsampler)
5292                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5293                 if (r_shadow_shadowmappcf > 1)
5294                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5295                 else if (r_shadow_shadowmappcf)
5296                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5297         }
5298         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
5299         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
5300         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
5301         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
5302         switch(vid.renderpath)
5303         {
5304         case RENDERPATH_GL20:
5305                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5306                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5307                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
5308                 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);
5309                 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);
5310                 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);
5311                 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]);
5312                 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]);
5313                 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));
5314                 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]);
5315                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5316
5317                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
5318                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
5319                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
5320                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
5321                 if (r_glsl_permutation->loc_Texture_ShadowMapRect     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT      , r_shadow_shadowmaprectangletexture                  );
5322                 if (r_shadow_usingshadowmapcube)
5323                         if (r_glsl_permutation->loc_Texture_ShadowMapCube     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE      , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5324                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
5325                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
5326                 break;
5327         case RENDERPATH_CGGL:
5328 #ifdef SUPPORTCG
5329                 R_SetupShader_SetPermutationCG(mode, permutation);
5330                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
5331                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
5332                 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
5333                 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
5334                 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
5335                 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
5336                 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
5337                 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
5338                 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
5339                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5340
5341                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
5342                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
5343                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
5344                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
5345                 if (r_cg_permutation->fp_Texture_ShadowMapRect    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
5346                 if (r_shadow_usingshadowmapcube)
5347                         if (r_cg_permutation->fp_Texture_ShadowMapCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5348                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5349                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
5350 #endif
5351                 break;
5352         case RENDERPATH_GL13:
5353         case RENDERPATH_GL11:
5354                 break;
5355         }
5356 }
5357
5358 #define SKINFRAME_HASH 1024
5359
5360 typedef struct
5361 {
5362         int loadsequence; // incremented each level change
5363         memexpandablearray_t array;
5364         skinframe_t *hash[SKINFRAME_HASH];
5365 }
5366 r_skinframe_t;
5367 r_skinframe_t r_skinframe;
5368
5369 void R_SkinFrame_PrepareForPurge(void)
5370 {
5371         r_skinframe.loadsequence++;
5372         // wrap it without hitting zero
5373         if (r_skinframe.loadsequence >= 200)
5374                 r_skinframe.loadsequence = 1;
5375 }
5376
5377 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5378 {
5379         if (!skinframe)
5380                 return;
5381         // mark the skinframe as used for the purging code
5382         skinframe->loadsequence = r_skinframe.loadsequence;
5383 }
5384
5385 void R_SkinFrame_Purge(void)
5386 {
5387         int i;
5388         skinframe_t *s;
5389         for (i = 0;i < SKINFRAME_HASH;i++)
5390         {
5391                 for (s = r_skinframe.hash[i];s;s = s->next)
5392                 {
5393                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5394                         {
5395                                 if (s->merged == s->base)
5396                                         s->merged = NULL;
5397                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5398                                 R_PurgeTexture(s->stain );s->stain  = NULL;
5399                                 R_PurgeTexture(s->merged);s->merged = NULL;
5400                                 R_PurgeTexture(s->base  );s->base   = NULL;
5401                                 R_PurgeTexture(s->pants );s->pants  = NULL;
5402                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
5403                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
5404                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
5405                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
5406                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
5407                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
5408                                 s->loadsequence = 0;
5409                         }
5410                 }
5411         }
5412 }
5413
5414 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5415         skinframe_t *item;
5416         char basename[MAX_QPATH];
5417
5418         Image_StripImageExtension(name, basename, sizeof(basename));
5419
5420         if( last == NULL ) {
5421                 int hashindex;
5422                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5423                 item = r_skinframe.hash[hashindex];
5424         } else {
5425                 item = last->next;
5426         }
5427
5428         // linearly search through the hash bucket
5429         for( ; item ; item = item->next ) {
5430                 if( !strcmp( item->basename, basename ) ) {
5431                         return item;
5432                 }
5433         }
5434         return NULL;
5435 }
5436
5437 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5438 {
5439         skinframe_t *item;
5440         int hashindex;
5441         char basename[MAX_QPATH];
5442
5443         Image_StripImageExtension(name, basename, sizeof(basename));
5444
5445         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5446         for (item = r_skinframe.hash[hashindex];item;item = item->next)
5447                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5448                         break;
5449
5450         if (!item) {
5451                 rtexture_t *dyntexture;
5452                 // check whether its a dynamic texture
5453                 dyntexture = CL_GetDynTexture( basename );
5454                 if (!add && !dyntexture)
5455                         return NULL;
5456                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5457                 memset(item, 0, sizeof(*item));
5458                 strlcpy(item->basename, basename, sizeof(item->basename));
5459                 item->base = dyntexture; // either NULL or dyntexture handle
5460                 item->textureflags = textureflags;
5461                 item->comparewidth = comparewidth;
5462                 item->compareheight = compareheight;
5463                 item->comparecrc = comparecrc;
5464                 item->next = r_skinframe.hash[hashindex];
5465                 r_skinframe.hash[hashindex] = item;
5466         }
5467         else if( item->base == NULL )
5468         {
5469                 rtexture_t *dyntexture;
5470                 // check whether its a dynamic texture
5471                 // 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]
5472                 dyntexture = CL_GetDynTexture( basename );
5473                 item->base = dyntexture; // either NULL or dyntexture handle
5474         }
5475
5476         R_SkinFrame_MarkUsed(item);
5477         return item;
5478 }
5479
5480 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5481         { \
5482                 unsigned long long avgcolor[5], wsum; \
5483                 int pix, comp, w; \
5484                 avgcolor[0] = 0; \
5485                 avgcolor[1] = 0; \
5486                 avgcolor[2] = 0; \
5487                 avgcolor[3] = 0; \
5488                 avgcolor[4] = 0; \
5489                 wsum = 0; \
5490                 for(pix = 0; pix < cnt; ++pix) \
5491                 { \
5492                         w = 0; \
5493                         for(comp = 0; comp < 3; ++comp) \
5494                                 w += getpixel; \
5495                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5496                         { \
5497                                 ++wsum; \
5498                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5499                                 w = getpixel; \
5500                                 for(comp = 0; comp < 3; ++comp) \
5501                                         avgcolor[comp] += getpixel * w; \
5502                                 avgcolor[3] += w; \
5503                         } \
5504                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5505                         avgcolor[4] += getpixel; \
5506                 } \
5507                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5508                         avgcolor[3] = 1; \
5509                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5510                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5511                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5512                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5513         }
5514
5515 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5516 {
5517         int j;
5518         unsigned char *pixels;
5519         unsigned char *bumppixels;
5520         unsigned char *basepixels = NULL;
5521         int basepixels_width = 0;
5522         int basepixels_height = 0;
5523         skinframe_t *skinframe;
5524         rtexture_t *ddsbase = NULL;
5525         qboolean ddshasalpha = false;
5526         float ddsavgcolor[4];
5527         char basename[MAX_QPATH];
5528
5529         if (cls.state == ca_dedicated)
5530                 return NULL;
5531
5532         // return an existing skinframe if already loaded
5533         // if loading of the first image fails, don't make a new skinframe as it
5534         // would cause all future lookups of this to be missing
5535         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5536         if (skinframe && skinframe->base)
5537                 return skinframe;
5538
5539         Image_StripImageExtension(name, basename, sizeof(basename));
5540
5541         // check for DDS texture file first
5542         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor)))
5543         {
5544                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer);
5545                 if (basepixels == NULL)
5546                         return NULL;
5547         }
5548
5549         if (developer_loading.integer)
5550                 Con_Printf("loading skin \"%s\"\n", name);
5551
5552         // we've got some pixels to store, so really allocate this new texture now
5553         if (!skinframe)
5554                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5555         skinframe->stain = NULL;
5556         skinframe->merged = NULL;
5557         skinframe->base = NULL;
5558         skinframe->pants = NULL;
5559         skinframe->shirt = NULL;
5560         skinframe->nmap = NULL;
5561         skinframe->gloss = NULL;
5562         skinframe->glow = NULL;
5563         skinframe->fog = NULL;
5564         skinframe->reflect = NULL;
5565         skinframe->hasalpha = false;
5566
5567         if (ddsbase)
5568         {
5569                 skinframe->base = ddsbase;
5570                 skinframe->hasalpha = ddshasalpha;
5571                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5572                 if (r_loadfog && skinframe->hasalpha)
5573                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5574                 //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]);
5575         }
5576         else
5577         {
5578                 basepixels_width = image_width;
5579                 basepixels_height = image_height;
5580                 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);
5581                 if (textureflags & TEXF_ALPHA)
5582                 {
5583                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5584                         {
5585                                 if (basepixels[j] < 255)
5586                                 {
5587                                         skinframe->hasalpha = true;
5588                                         break;
5589                                 }
5590                         }
5591                         if (r_loadfog && skinframe->hasalpha)
5592                         {
5593                                 // has transparent pixels
5594                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5595                                 for (j = 0;j < image_width * image_height * 4;j += 4)
5596                                 {
5597                                         pixels[j+0] = 255;
5598                                         pixels[j+1] = 255;
5599                                         pixels[j+2] = 255;
5600                                         pixels[j+3] = basepixels[j+3];
5601                                 }
5602                                 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);
5603                                 Mem_Free(pixels);
5604                         }
5605                 }
5606                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5607                 //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]);
5608                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5609                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true);
5610                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
5611                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true);
5612         }
5613
5614         if (r_loaddds)
5615         {
5616                 if (r_loadnormalmap)
5617                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5618                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL);
5619                 if (r_loadgloss)
5620                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL);
5621                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL);
5622                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL);
5623                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL);
5624         }
5625
5626         // _norm is the name used by tenebrae and has been adopted as standard
5627         if (r_loadnormalmap && skinframe->nmap == NULL)
5628         {
5629                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false)) != NULL)
5630                 {
5631                         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);
5632                         Mem_Free(pixels);
5633                         pixels = NULL;
5634                 }
5635                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false)) != NULL)
5636                 {
5637                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5638                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5639                         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);
5640                         Mem_Free(pixels);
5641                         Mem_Free(bumppixels);
5642                 }
5643                 else if (r_shadow_bumpscale_basetexture.value > 0)
5644                 {
5645                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5646                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5647                         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);
5648                         Mem_Free(pixels);
5649                 }
5650                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
5651                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true);
5652         }
5653
5654         // _luma is supported only for tenebrae compatibility
5655         // _glow is the preferred name
5656         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))))
5657         {
5658                 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);
5659                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
5660                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true);
5661                 Mem_Free(pixels);pixels = NULL;
5662         }
5663
5664         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5665         {
5666                 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);
5667                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
5668                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true);
5669                 Mem_Free(pixels);
5670                 pixels = NULL;
5671         }
5672
5673         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5674         {
5675                 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);
5676                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
5677                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true);
5678                 Mem_Free(pixels);
5679                 pixels = NULL;
5680         }
5681
5682         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5683         {
5684                 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);
5685                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
5686                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true);
5687                 Mem_Free(pixels);
5688                 pixels = NULL;
5689         }
5690
5691         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5692         {
5693                 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);
5694                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
5695                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true);
5696                 Mem_Free(pixels);
5697                 pixels = NULL;
5698         }
5699
5700         if (basepixels)
5701                 Mem_Free(basepixels);
5702
5703         return skinframe;
5704 }
5705
5706 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
5707 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
5708 {
5709         int i;
5710         unsigned char *temp1, *temp2;
5711         skinframe_t *skinframe;
5712
5713         if (cls.state == ca_dedicated)
5714                 return NULL;
5715
5716         // if already loaded just return it, otherwise make a new skinframe
5717         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
5718         if (skinframe && skinframe->base)
5719                 return skinframe;
5720
5721         skinframe->stain = NULL;
5722         skinframe->merged = NULL;
5723         skinframe->base = NULL;
5724         skinframe->pants = NULL;
5725         skinframe->shirt = NULL;
5726         skinframe->nmap = NULL;
5727         skinframe->gloss = NULL;
5728         skinframe->glow = NULL;
5729         skinframe->fog = NULL;
5730         skinframe->reflect = NULL;
5731         skinframe->hasalpha = false;
5732
5733         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5734         if (!skindata)
5735                 return NULL;
5736
5737         if (developer_loading.integer)
5738                 Con_Printf("loading 32bit skin \"%s\"\n", name);
5739
5740         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
5741         {
5742                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5743                 temp2 = temp1 + width * height * 4;
5744                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5745                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5746                 Mem_Free(temp1);
5747         }
5748         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5749         if (textureflags & TEXF_ALPHA)
5750         {
5751                 for (i = 3;i < width * height * 4;i += 4)
5752                 {
5753                         if (skindata[i] < 255)
5754                         {
5755                                 skinframe->hasalpha = true;
5756                                 break;
5757                         }
5758                 }
5759                 if (r_loadfog && skinframe->hasalpha)
5760                 {
5761                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
5762                         memcpy(fogpixels, skindata, width * height * 4);
5763                         for (i = 0;i < width * height * 4;i += 4)
5764                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
5765                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5766                         Mem_Free(fogpixels);
5767                 }
5768         }
5769
5770         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
5771         //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]);
5772
5773         return skinframe;
5774 }
5775
5776 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
5777 {
5778         int i;
5779         int featuresmask;
5780         skinframe_t *skinframe;
5781
5782         if (cls.state == ca_dedicated)
5783                 return NULL;
5784
5785         // if already loaded just return it, otherwise make a new skinframe
5786         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5787         if (skinframe && skinframe->base)
5788                 return skinframe;
5789
5790         skinframe->stain = NULL;
5791         skinframe->merged = NULL;
5792         skinframe->base = NULL;
5793         skinframe->pants = NULL;
5794         skinframe->shirt = NULL;
5795         skinframe->nmap = NULL;
5796         skinframe->gloss = NULL;
5797         skinframe->glow = NULL;
5798         skinframe->fog = NULL;
5799         skinframe->reflect = NULL;
5800         skinframe->hasalpha = false;
5801
5802         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5803         if (!skindata)
5804                 return NULL;
5805
5806         if (developer_loading.integer)
5807                 Con_Printf("loading quake skin \"%s\"\n", name);
5808
5809         // 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)
5810         skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
5811         memcpy(skinframe->qpixels, skindata, width*height);
5812         skinframe->qwidth = width;
5813         skinframe->qheight = height;
5814
5815         featuresmask = 0;
5816         for (i = 0;i < width * height;i++)
5817                 featuresmask |= palette_featureflags[skindata[i]];
5818
5819         skinframe->hasalpha = false;
5820         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
5821         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
5822         skinframe->qgeneratemerged = true;
5823         skinframe->qgeneratebase = skinframe->qhascolormapping;
5824         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
5825
5826         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
5827         //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]);
5828
5829         return skinframe;
5830 }
5831
5832 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
5833 {
5834         int width;
5835         int height;
5836         unsigned char *skindata;
5837
5838         if (!skinframe->qpixels)
5839                 return;
5840
5841         if (!skinframe->qhascolormapping)
5842                 colormapped = false;
5843
5844         if (colormapped)
5845         {
5846                 if (!skinframe->qgeneratebase)
5847                         return;
5848         }
5849         else
5850         {
5851                 if (!skinframe->qgeneratemerged)
5852                         return;
5853         }
5854
5855         width = skinframe->qwidth;
5856         height = skinframe->qheight;
5857         skindata = skinframe->qpixels;
5858
5859         if (skinframe->qgeneratenmap)
5860         {
5861                 unsigned char *temp1, *temp2;
5862                 skinframe->qgeneratenmap = false;
5863                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5864                 temp2 = temp1 + width * height * 4;
5865                 // use either a custom palette or the quake palette
5866                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
5867                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5868                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5869                 Mem_Free(temp1);
5870         }
5871
5872         if (skinframe->qgenerateglow)
5873         {
5874                 skinframe->qgenerateglow = false;
5875                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
5876         }
5877
5878         if (colormapped)
5879         {
5880                 skinframe->qgeneratebase = false;
5881                 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);
5882                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
5883                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
5884         }
5885         else
5886         {
5887                 skinframe->qgeneratemerged = false;
5888                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
5889         }
5890
5891         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
5892         {
5893                 Mem_Free(skinframe->qpixels);
5894                 skinframe->qpixels = NULL;
5895         }
5896 }
5897
5898 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)
5899 {
5900         int i;
5901         skinframe_t *skinframe;
5902
5903         if (cls.state == ca_dedicated)
5904                 return NULL;
5905
5906         // if already loaded just return it, otherwise make a new skinframe
5907         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5908         if (skinframe && skinframe->base)
5909                 return skinframe;
5910
5911         skinframe->stain = NULL;
5912         skinframe->merged = NULL;
5913         skinframe->base = NULL;
5914         skinframe->pants = NULL;
5915         skinframe->shirt = NULL;
5916         skinframe->nmap = NULL;
5917         skinframe->gloss = NULL;
5918         skinframe->glow = NULL;
5919         skinframe->fog = NULL;
5920         skinframe->reflect = NULL;
5921         skinframe->hasalpha = false;
5922
5923         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5924         if (!skindata)
5925                 return NULL;
5926
5927         if (developer_loading.integer)
5928                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
5929
5930         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
5931         if (textureflags & TEXF_ALPHA)
5932         {
5933                 for (i = 0;i < width * height;i++)
5934                 {
5935                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
5936                         {
5937                                 skinframe->hasalpha = true;
5938                                 break;
5939                         }
5940                 }
5941                 if (r_loadfog && skinframe->hasalpha)
5942                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
5943         }
5944
5945         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
5946         //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]);
5947
5948         return skinframe;
5949 }
5950
5951 skinframe_t *R_SkinFrame_LoadMissing(void)
5952 {
5953         skinframe_t *skinframe;
5954
5955         if (cls.state == ca_dedicated)
5956                 return NULL;
5957
5958         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
5959         skinframe->stain = NULL;
5960         skinframe->merged = NULL;
5961         skinframe->base = NULL;
5962         skinframe->pants = NULL;
5963         skinframe->shirt = NULL;
5964         skinframe->nmap = NULL;
5965         skinframe->gloss = NULL;
5966         skinframe->glow = NULL;
5967         skinframe->fog = NULL;
5968         skinframe->reflect = NULL;
5969         skinframe->hasalpha = false;
5970
5971         skinframe->avgcolor[0] = rand() / RAND_MAX;
5972         skinframe->avgcolor[1] = rand() / RAND_MAX;
5973         skinframe->avgcolor[2] = rand() / RAND_MAX;
5974         skinframe->avgcolor[3] = 1;
5975
5976         return skinframe;
5977 }
5978
5979 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
5980 typedef struct suffixinfo_s
5981 {
5982         char *suffix;
5983         qboolean flipx, flipy, flipdiagonal;
5984 }
5985 suffixinfo_t;
5986 static suffixinfo_t suffix[3][6] =
5987 {
5988         {
5989                 {"px",   false, false, false},
5990                 {"nx",   false, false, false},
5991                 {"py",   false, false, false},
5992                 {"ny",   false, false, false},
5993                 {"pz",   false, false, false},
5994                 {"nz",   false, false, false}
5995         },
5996         {
5997                 {"posx", false, false, false},
5998                 {"negx", false, false, false},
5999                 {"posy", false, false, false},
6000                 {"negy", false, false, false},
6001                 {"posz", false, false, false},
6002                 {"negz", false, false, false}
6003         },
6004         {
6005                 {"rt",    true, false,  true},
6006                 {"lf",   false,  true,  true},
6007                 {"ft",    true,  true, false},
6008                 {"bk",   false, false, false},
6009                 {"up",    true, false,  true},
6010                 {"dn",    true, false,  true}
6011         }
6012 };
6013
6014 static int componentorder[4] = {0, 1, 2, 3};
6015
6016 rtexture_t *R_LoadCubemap(const char *basename)
6017 {
6018         int i, j, cubemapsize;
6019         unsigned char *cubemappixels, *image_buffer;
6020         rtexture_t *cubemaptexture;
6021         char name[256];
6022         // must start 0 so the first loadimagepixels has no requested width/height
6023         cubemapsize = 0;
6024         cubemappixels = NULL;
6025         cubemaptexture = NULL;
6026         // keep trying different suffix groups (posx, px, rt) until one loads
6027         for (j = 0;j < 3 && !cubemappixels;j++)
6028         {
6029                 // load the 6 images in the suffix group
6030                 for (i = 0;i < 6;i++)
6031                 {
6032                         // generate an image name based on the base and and suffix
6033                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6034                         // load it
6035                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer)))
6036                         {
6037                                 // an image loaded, make sure width and height are equal
6038                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6039                                 {
6040                                         // if this is the first image to load successfully, allocate the cubemap memory
6041                                         if (!cubemappixels && image_width >= 1)
6042                                         {
6043                                                 cubemapsize = image_width;
6044                                                 // note this clears to black, so unavailable sides are black
6045                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6046                                         }
6047                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6048                                         if (cubemappixels)
6049                                                 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);
6050                                 }
6051                                 else
6052                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6053                                 // free the image
6054                                 Mem_Free(image_buffer);
6055                         }
6056                 }
6057         }
6058         // if a cubemap loaded, upload it
6059         if (cubemappixels)
6060         {
6061                 if (developer_loading.integer)
6062                         Con_Printf("loading cubemap \"%s\"\n", basename);
6063
6064                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR, NULL);
6065                 Mem_Free(cubemappixels);
6066         }
6067         else
6068         {
6069                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6070                 if (developer_loading.integer)
6071                 {
6072                         Con_Printf("(tried tried images ");
6073                         for (j = 0;j < 3;j++)
6074                                 for (i = 0;i < 6;i++)
6075                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
6076                         Con_Print(" and was unable to find any of them).\n");
6077                 }
6078         }
6079         return cubemaptexture;
6080 }
6081
6082 rtexture_t *R_GetCubemap(const char *basename)
6083 {
6084         int i;
6085         for (i = 0;i < r_texture_numcubemaps;i++)
6086                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6087                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6088         if (i >= MAX_CUBEMAPS)
6089                 return r_texture_whitecube;
6090         r_texture_numcubemaps++;
6091         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6092         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6093         return r_texture_cubemaps[i].texture;
6094 }
6095
6096 void R_FreeCubemaps(void)
6097 {
6098         int i;
6099         for (i = 0;i < r_texture_numcubemaps;i++)
6100         {
6101                 if (developer_loading.integer)
6102                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6103                 if (r_texture_cubemaps[i].texture)
6104                         R_FreeTexture(r_texture_cubemaps[i].texture);
6105         }
6106         r_texture_numcubemaps = 0;
6107 }
6108
6109 void R_Main_FreeViewCache(void)
6110 {
6111         if (r_refdef.viewcache.entityvisible)
6112                 Mem_Free(r_refdef.viewcache.entityvisible);
6113         if (r_refdef.viewcache.world_pvsbits)
6114                 Mem_Free(r_refdef.viewcache.world_pvsbits);
6115         if (r_refdef.viewcache.world_leafvisible)
6116                 Mem_Free(r_refdef.viewcache.world_leafvisible);
6117         if (r_refdef.viewcache.world_surfacevisible)
6118                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6119         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6120 }
6121
6122 void R_Main_ResizeViewCache(void)
6123 {
6124         int numentities = r_refdef.scene.numentities;
6125         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6126         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6127         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6128         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6129         if (r_refdef.viewcache.maxentities < numentities)
6130         {
6131                 r_refdef.viewcache.maxentities = numentities;
6132                 if (r_refdef.viewcache.entityvisible)
6133                         Mem_Free(r_refdef.viewcache.entityvisible);
6134                 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6135         }
6136         if (r_refdef.viewcache.world_numclusters != numclusters)
6137         {
6138                 r_refdef.viewcache.world_numclusters = numclusters;
6139                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6140                 if (r_refdef.viewcache.world_pvsbits)
6141                         Mem_Free(r_refdef.viewcache.world_pvsbits);
6142                 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6143         }
6144         if (r_refdef.viewcache.world_numleafs != numleafs)
6145         {
6146                 r_refdef.viewcache.world_numleafs = numleafs;
6147                 if (r_refdef.viewcache.world_leafvisible)
6148                         Mem_Free(r_refdef.viewcache.world_leafvisible);
6149                 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6150         }
6151         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6152         {
6153                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6154                 if (r_refdef.viewcache.world_surfacevisible)
6155                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
6156                 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6157         }
6158 }
6159
6160 extern rtexture_t *loadingscreentexture;
6161 void gl_main_start(void)
6162 {
6163         loadingscreentexture = NULL;
6164         r_texture_blanknormalmap = NULL;
6165         r_texture_white = NULL;
6166         r_texture_grey128 = NULL;
6167         r_texture_black = NULL;
6168         r_texture_whitecube = NULL;
6169         r_texture_normalizationcube = NULL;
6170         r_texture_fogattenuation = NULL;
6171         r_texture_fogheighttexture = NULL;
6172         r_texture_gammaramps = NULL;
6173         r_texture_numcubemaps = 0;
6174
6175         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
6176         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6177
6178         switch(vid.renderpath)
6179         {
6180         case RENDERPATH_GL20:
6181         case RENDERPATH_CGGL:
6182                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6183                 Cvar_SetValueQuick(&gl_combine, 1);
6184                 Cvar_SetValueQuick(&r_glsl, 1);
6185                 r_loadnormalmap = true;
6186                 r_loadgloss = true;
6187                 r_loadfog = false;
6188                 break;
6189         case RENDERPATH_GL13:
6190                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6191                 Cvar_SetValueQuick(&gl_combine, 1);
6192                 Cvar_SetValueQuick(&r_glsl, 0);
6193                 r_loadnormalmap = false;
6194                 r_loadgloss = false;
6195                 r_loadfog = true;
6196                 break;
6197         case RENDERPATH_GL11:
6198                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6199                 Cvar_SetValueQuick(&gl_combine, 0);
6200                 Cvar_SetValueQuick(&r_glsl, 0);
6201                 r_loadnormalmap = false;
6202                 r_loadgloss = false;
6203                 r_loadfog = true;
6204                 break;
6205         }
6206
6207         R_AnimCache_Free();
6208         R_FrameData_Reset();
6209
6210         r_numqueries = 0;
6211         r_maxqueries = 0;
6212         memset(r_queries, 0, sizeof(r_queries));
6213
6214         r_qwskincache = NULL;
6215         r_qwskincache_size = 0;
6216
6217         // set up r_skinframe loading system for textures
6218         memset(&r_skinframe, 0, sizeof(r_skinframe));
6219         r_skinframe.loadsequence = 1;
6220         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
6221
6222         r_main_texturepool = R_AllocTexturePool();
6223         R_BuildBlankTextures();
6224         R_BuildNoTexture();
6225         if (vid.support.arb_texture_cube_map)
6226         {
6227                 R_BuildWhiteCube();
6228                 R_BuildNormalizationCube();
6229         }
6230         r_texture_fogattenuation = NULL;
6231         r_texture_fogheighttexture = NULL;
6232         r_texture_gammaramps = NULL;
6233         //r_texture_fogintensity = NULL;
6234         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6235         memset(&r_waterstate, 0, sizeof(r_waterstate));
6236         r_glsl_permutation = NULL;
6237         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6238         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
6239         glslshaderstring = NULL;
6240 #ifdef SUPPORTCG
6241         r_cg_permutation = NULL;
6242         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
6243         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
6244         cgshaderstring = NULL;
6245 #endif
6246         memset(&r_svbsp, 0, sizeof (r_svbsp));
6247
6248         r_refdef.fogmasktable_density = 0;
6249 }
6250
6251 void gl_main_shutdown(void)
6252 {
6253         R_AnimCache_Free();
6254         R_FrameData_Reset();
6255
6256         R_Main_FreeViewCache();
6257
6258         if (r_maxqueries)
6259                 qglDeleteQueriesARB(r_maxqueries, r_queries);
6260
6261         r_numqueries = 0;
6262         r_maxqueries = 0;
6263         memset(r_queries, 0, sizeof(r_queries));
6264
6265         r_qwskincache = NULL;
6266         r_qwskincache_size = 0;
6267
6268         // clear out the r_skinframe state
6269         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
6270         memset(&r_skinframe, 0, sizeof(r_skinframe));
6271
6272         if (r_svbsp.nodes)
6273                 Mem_Free(r_svbsp.nodes);
6274         memset(&r_svbsp, 0, sizeof (r_svbsp));
6275         R_FreeTexturePool(&r_main_texturepool);
6276         loadingscreentexture = NULL;
6277         r_texture_blanknormalmap = NULL;
6278         r_texture_white = NULL;
6279         r_texture_grey128 = NULL;
6280         r_texture_black = NULL;
6281         r_texture_whitecube = NULL;
6282         r_texture_normalizationcube = NULL;
6283         r_texture_fogattenuation = NULL;
6284         r_texture_fogheighttexture = NULL;
6285         r_texture_gammaramps = NULL;
6286         r_texture_numcubemaps = 0;
6287         //r_texture_fogintensity = NULL;
6288         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6289         memset(&r_waterstate, 0, sizeof(r_waterstate));
6290         r_glsl_permutation = NULL;
6291         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6292         glslshaderstring = NULL;
6293 #ifdef SUPPORTCG
6294         r_cg_permutation = NULL;
6295         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
6296         cgshaderstring = NULL;
6297 #endif
6298         R_GLSL_Restart_f();
6299 }
6300
6301 extern void CL_ParseEntityLump(char *entitystring);
6302 void gl_main_newmap(void)
6303 {
6304         // FIXME: move this code to client
6305         int l;
6306         char *entities, entname[MAX_QPATH];
6307         if (r_qwskincache)
6308                 Mem_Free(r_qwskincache);
6309         r_qwskincache = NULL;
6310         r_qwskincache_size = 0;
6311         if (cl.worldmodel)
6312         {
6313                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
6314                 l = (int)strlen(entname) - 4;
6315                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
6316                 {
6317                         memcpy(entname + l, ".ent", 5);
6318                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
6319                         {
6320                                 CL_ParseEntityLump(entities);
6321                                 Mem_Free(entities);
6322                                 return;
6323                         }
6324                 }
6325                 if (cl.worldmodel->brush.entities)
6326                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
6327         }
6328         R_Main_FreeViewCache();
6329
6330         R_FrameData_Reset();
6331 }
6332
6333 void GL_Main_Init(void)
6334 {
6335         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
6336
6337         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
6338         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
6339         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
6340         if (gamemode == GAME_NEHAHRA)
6341         {
6342                 Cvar_RegisterVariable (&gl_fogenable);
6343                 Cvar_RegisterVariable (&gl_fogdensity);
6344                 Cvar_RegisterVariable (&gl_fogred);
6345                 Cvar_RegisterVariable (&gl_foggreen);
6346                 Cvar_RegisterVariable (&gl_fogblue);
6347                 Cvar_RegisterVariable (&gl_fogstart);
6348                 Cvar_RegisterVariable (&gl_fogend);
6349                 Cvar_RegisterVariable (&gl_skyclip);
6350         }
6351         Cvar_RegisterVariable(&r_motionblur);
6352         Cvar_RegisterVariable(&r_motionblur_maxblur);
6353         Cvar_RegisterVariable(&r_motionblur_bmin);
6354         Cvar_RegisterVariable(&r_motionblur_vmin);
6355         Cvar_RegisterVariable(&r_motionblur_vmax);
6356         Cvar_RegisterVariable(&r_motionblur_vcoeff);
6357         Cvar_RegisterVariable(&r_motionblur_randomize);
6358         Cvar_RegisterVariable(&r_damageblur);
6359         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
6360         Cvar_RegisterVariable(&r_equalize_entities_minambient);
6361         Cvar_RegisterVariable(&r_equalize_entities_by);
6362         Cvar_RegisterVariable(&r_equalize_entities_to);
6363         Cvar_RegisterVariable(&r_depthfirst);
6364         Cvar_RegisterVariable(&r_useinfinitefarclip);
6365         Cvar_RegisterVariable(&r_farclip_base);
6366         Cvar_RegisterVariable(&r_farclip_world);
6367         Cvar_RegisterVariable(&r_nearclip);
6368         Cvar_RegisterVariable(&r_showbboxes);
6369         Cvar_RegisterVariable(&r_showsurfaces);
6370         Cvar_RegisterVariable(&r_showtris);
6371         Cvar_RegisterVariable(&r_shownormals);
6372         Cvar_RegisterVariable(&r_showlighting);
6373         Cvar_RegisterVariable(&r_showshadowvolumes);
6374         Cvar_RegisterVariable(&r_showcollisionbrushes);
6375         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
6376         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
6377         Cvar_RegisterVariable(&r_showdisabledepthtest);
6378         Cvar_RegisterVariable(&r_drawportals);
6379         Cvar_RegisterVariable(&r_drawentities);
6380         Cvar_RegisterVariable(&r_cullentities_trace);
6381         Cvar_RegisterVariable(&r_cullentities_trace_samples);
6382         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
6383         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
6384         Cvar_RegisterVariable(&r_cullentities_trace_delay);
6385         Cvar_RegisterVariable(&r_drawviewmodel);
6386         Cvar_RegisterVariable(&r_drawexteriormodel);
6387         Cvar_RegisterVariable(&r_speeds);
6388         Cvar_RegisterVariable(&r_fullbrights);
6389         Cvar_RegisterVariable(&r_wateralpha);
6390         Cvar_RegisterVariable(&r_dynamic);
6391         Cvar_RegisterVariable(&r_fullbright);
6392         Cvar_RegisterVariable(&r_shadows);
6393         Cvar_RegisterVariable(&r_shadows_darken);
6394         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
6395         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
6396         Cvar_RegisterVariable(&r_shadows_throwdistance);
6397         Cvar_RegisterVariable(&r_shadows_throwdirection);
6398         Cvar_RegisterVariable(&r_shadows_focus);
6399         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
6400         Cvar_RegisterVariable(&r_q1bsp_skymasking);
6401         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
6402         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
6403         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
6404         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
6405         Cvar_RegisterVariable(&r_fog_exp2);
6406         Cvar_RegisterVariable(&r_drawfog);
6407         Cvar_RegisterVariable(&r_transparentdepthmasking);
6408         Cvar_RegisterVariable(&r_texture_dds_load);
6409         Cvar_RegisterVariable(&r_texture_dds_save);
6410         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
6411         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
6412         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
6413         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
6414         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
6415         Cvar_RegisterVariable(&r_textureunits);
6416         Cvar_RegisterVariable(&gl_combine);
6417         Cvar_RegisterVariable(&r_glsl);
6418         Cvar_RegisterVariable(&r_glsl_deluxemapping);
6419         Cvar_RegisterVariable(&r_glsl_offsetmapping);
6420         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
6421         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
6422         Cvar_RegisterVariable(&r_glsl_postprocess);
6423         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
6424         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
6425         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
6426         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
6427 //      Cvar_RegisterVariable(&r_glsl_postprocess_sobel);
6428         Cvar_RegisterVariable(&r_water);
6429         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
6430         Cvar_RegisterVariable(&r_water_clippingplanebias);
6431         Cvar_RegisterVariable(&r_water_refractdistort);
6432         Cvar_RegisterVariable(&r_water_reflectdistort);
6433         Cvar_RegisterVariable(&r_lerpsprites);
6434         Cvar_RegisterVariable(&r_lerpmodels);
6435         Cvar_RegisterVariable(&r_lerplightstyles);
6436         Cvar_RegisterVariable(&r_waterscroll);
6437         Cvar_RegisterVariable(&r_bloom);
6438         Cvar_RegisterVariable(&r_bloom_colorscale);
6439         Cvar_RegisterVariable(&r_bloom_brighten);
6440         Cvar_RegisterVariable(&r_bloom_blur);
6441         Cvar_RegisterVariable(&r_bloom_resolution);
6442         Cvar_RegisterVariable(&r_bloom_colorexponent);
6443         Cvar_RegisterVariable(&r_bloom_colorsubtract);
6444         Cvar_RegisterVariable(&r_hdr);
6445         Cvar_RegisterVariable(&r_hdr_scenebrightness);
6446         Cvar_RegisterVariable(&r_hdr_glowintensity);
6447         Cvar_RegisterVariable(&r_hdr_range);
6448         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
6449         Cvar_RegisterVariable(&developer_texturelogging);
6450         Cvar_RegisterVariable(&gl_lightmaps);
6451         Cvar_RegisterVariable(&r_test);
6452         Cvar_RegisterVariable(&r_glsl_saturation);
6453         Cvar_RegisterVariable(&r_framedatasize);
6454         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
6455                 Cvar_SetValue("r_fullbrights", 0);
6456         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
6457
6458         Cvar_RegisterVariable(&r_track_sprites);
6459         Cvar_RegisterVariable(&r_track_sprites_flags);
6460         Cvar_RegisterVariable(&r_track_sprites_scalew);
6461         Cvar_RegisterVariable(&r_track_sprites_scaleh);
6462         Cvar_RegisterVariable(&r_overheadsprites_perspective);
6463         Cvar_RegisterVariable(&r_overheadsprites_pushback);
6464 }
6465
6466 extern void R_Textures_Init(void);
6467 extern void GL_Draw_Init(void);
6468 extern void GL_Main_Init(void);
6469 extern void R_Shadow_Init(void);
6470 extern void R_Sky_Init(void);
6471 extern void GL_Surf_Init(void);
6472 extern void R_Particles_Init(void);
6473 extern void R_Explosion_Init(void);
6474 extern void gl_backend_init(void);
6475 extern void Sbar_Init(void);
6476 extern void R_LightningBeams_Init(void);
6477 extern void Mod_RenderInit(void);
6478 extern void Font_Init(void);
6479
6480 void Render_Init(void)
6481 {
6482         gl_backend_init();
6483         R_Textures_Init();
6484         GL_Main_Init();
6485         Font_Init();
6486         GL_Draw_Init();
6487         R_Shadow_Init();
6488         R_Sky_Init();
6489         GL_Surf_Init();
6490         Sbar_Init();
6491         R_Particles_Init();
6492         R_Explosion_Init();
6493         R_LightningBeams_Init();
6494         Mod_RenderInit();
6495 }
6496
6497 /*
6498 ===============
6499 GL_Init
6500 ===============
6501 */
6502 extern char *ENGINE_EXTENSIONS;
6503 void GL_Init (void)
6504 {
6505         gl_renderer = (const char *)qglGetString(GL_RENDERER);
6506         gl_vendor = (const char *)qglGetString(GL_VENDOR);
6507         gl_version = (const char *)qglGetString(GL_VERSION);
6508         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
6509
6510         if (!gl_extensions)
6511                 gl_extensions = "";
6512         if (!gl_platformextensions)
6513                 gl_platformextensions = "";
6514
6515         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
6516         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
6517         Con_Printf("GL_VERSION: %s\n", gl_version);
6518         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
6519         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
6520
6521         VID_CheckExtensions();
6522
6523         // LordHavoc: report supported extensions
6524         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
6525
6526         // clear to black (loading plaque will be seen over this)
6527         CHECKGLERROR
6528         qglClearColor(0,0,0,1);CHECKGLERROR
6529         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
6530 }
6531
6532 int R_CullBox(const vec3_t mins, const vec3_t maxs)
6533 {
6534         int i;
6535         mplane_t *p;
6536         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6537         {
6538                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
6539                 if (i == 4)
6540                         continue;
6541                 p = r_refdef.view.frustum + i;
6542                 switch(p->signbits)
6543                 {
6544                 default:
6545                 case 0:
6546                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6547                                 return true;
6548                         break;
6549                 case 1:
6550                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6551                                 return true;
6552                         break;
6553                 case 2:
6554                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6555                                 return true;
6556                         break;
6557                 case 3:
6558                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6559                                 return true;
6560                         break;
6561                 case 4:
6562                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6563                                 return true;
6564                         break;
6565                 case 5:
6566                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6567                                 return true;
6568                         break;
6569                 case 6:
6570                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6571                                 return true;
6572                         break;
6573                 case 7:
6574                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6575                                 return true;
6576                         break;
6577                 }
6578         }
6579         return false;
6580 }
6581
6582 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
6583 {
6584         int i;
6585         const mplane_t *p;
6586         for (i = 0;i < numplanes;i++)
6587         {
6588                 p = planes + i;
6589                 switch(p->signbits)
6590                 {
6591                 default:
6592                 case 0:
6593                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6594                                 return true;
6595                         break;
6596                 case 1:
6597                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6598                                 return true;
6599                         break;
6600                 case 2:
6601                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6602                                 return true;
6603                         break;
6604                 case 3:
6605                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6606                                 return true;
6607                         break;
6608                 case 4:
6609                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6610                                 return true;
6611                         break;
6612                 case 5:
6613                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6614                                 return true;
6615                         break;
6616                 case 6:
6617                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6618                                 return true;
6619                         break;
6620                 case 7:
6621                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6622                                 return true;
6623                         break;
6624                 }
6625         }
6626         return false;
6627 }
6628
6629 //==================================================================================
6630
6631 // LordHavoc: this stores temporary data used within the same frame
6632
6633 qboolean r_framedata_failed;
6634 static size_t r_framedata_size;
6635 static size_t r_framedata_current;
6636 static void *r_framedata_base;
6637
6638 void R_FrameData_Reset(void)
6639 {
6640         if (r_framedata_base)
6641                 Mem_Free(r_framedata_base);
6642         r_framedata_base = NULL;
6643         r_framedata_size = 0;
6644         r_framedata_current = 0;
6645         r_framedata_failed = false;
6646 }
6647
6648 void R_FrameData_NewFrame(void)
6649 {
6650         size_t wantedsize;
6651         if (r_framedata_failed)
6652                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
6653         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
6654         wantedsize = bound(65536, wantedsize, 128*1024*1024);
6655         if (r_framedata_size != wantedsize)
6656         {
6657                 r_framedata_size = wantedsize;
6658                 if (r_framedata_base)
6659                         Mem_Free(r_framedata_base);
6660                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
6661         }
6662         r_framedata_current = 0;
6663         r_framedata_failed = false;
6664 }
6665
6666 void *R_FrameData_Alloc(size_t size)
6667 {
6668         void *data;
6669
6670         // align to 16 byte boundary
6671         size = (size + 15) & ~15;
6672         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
6673         r_framedata_current += size;
6674
6675         // check overflow
6676         if (r_framedata_current > r_framedata_size)
6677                 r_framedata_failed = true;
6678
6679         // return NULL on everything after a failure
6680         if (r_framedata_failed)
6681                 return NULL;
6682
6683         return data;
6684 }
6685
6686 void *R_FrameData_Store(size_t size, void *data)
6687 {
6688         void *d = R_FrameData_Alloc(size);
6689         if (d)
6690                 memcpy(d, data, size);
6691         return d;
6692 }
6693
6694 //==================================================================================
6695
6696 // LordHavoc: animcache originally written by Echon, rewritten since then
6697
6698 /**
6699  * Animation cache prevents re-generating mesh data for an animated model
6700  * multiple times in one frame for lighting, shadowing, reflections, etc.
6701  */
6702
6703 void R_AnimCache_Free(void)
6704 {
6705 }
6706
6707 void R_AnimCache_ClearCache(void)
6708 {
6709         int i;
6710         entity_render_t *ent;
6711
6712         for (i = 0;i < r_refdef.scene.numentities;i++)
6713         {
6714                 ent = r_refdef.scene.entities[i];
6715                 ent->animcache_vertex3f = NULL;
6716                 ent->animcache_normal3f = NULL;
6717                 ent->animcache_svector3f = NULL;
6718                 ent->animcache_tvector3f = NULL;
6719                 ent->animcache_vertexposition = NULL;
6720                 ent->animcache_vertexmesh = NULL;
6721                 ent->animcache_vertexpositionbuffer = NULL;
6722                 ent->animcache_vertexmeshbuffer = NULL;
6723         }
6724 }
6725
6726 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
6727 {
6728         int i;
6729         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
6730                 ent->animcache_vertexmesh = R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
6731         if (!ent->animcache_vertexposition)
6732                 ent->animcache_vertexposition = R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
6733         if (ent->animcache_vertexposition)
6734         {
6735                 for (i = 0;i < numvertices;i++)
6736                         VectorCopy(ent->animcache_vertex3f + 3*i, ent->animcache_vertexposition[i].vertex3f);
6737                 // TODO: upload vertex buffer?
6738         }
6739         if (ent->animcache_vertexmesh)
6740         {
6741                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
6742                 for (i = 0;i < numvertices;i++)
6743                         VectorCopy(ent->animcache_vertex3f + 3*i, ent->animcache_vertexmesh[i].vertex3f);
6744                 if (ent->animcache_svector3f)
6745                         for (i = 0;i < numvertices;i++)
6746                                 VectorCopy(ent->animcache_svector3f + 3*i, ent->animcache_vertexmesh[i].svector3f);
6747                 if (ent->animcache_tvector3f)
6748                         for (i = 0;i < numvertices;i++)
6749                                 VectorCopy(ent->animcache_tvector3f + 3*i, ent->animcache_vertexmesh[i].tvector3f);
6750                 if (ent->animcache_normal3f)
6751                         for (i = 0;i < numvertices;i++)
6752                                 VectorCopy(ent->animcache_normal3f + 3*i, ent->animcache_vertexmesh[i].normal3f);
6753                 // TODO: upload vertex buffer?
6754         }
6755 }
6756
6757 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6758 {
6759         dp_model_t *model = ent->model;
6760         int numvertices;
6761         // see if it's already cached this frame
6762         if (ent->animcache_vertex3f)
6763         {
6764                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
6765                 if (wantnormals || wanttangents)
6766                 {
6767                         if (ent->animcache_normal3f)
6768                                 wantnormals = false;
6769                         if (ent->animcache_svector3f)
6770                                 wanttangents = false;
6771                         if (wantnormals || wanttangents)
6772                         {
6773                                 numvertices = model->surfmesh.num_vertices;
6774                                 if (wantnormals)
6775                                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6776                                 if (wanttangents)
6777                                 {
6778                                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6779                                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6780                                 }
6781                                 if (!r_framedata_failed)
6782                                 {
6783                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
6784                                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
6785                                 }
6786                         }
6787                 }
6788         }
6789         else
6790         {
6791                 // see if this ent is worth caching
6792                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
6793                         return false;
6794                 // get some memory for this entity and generate mesh data
6795                 numvertices = model->surfmesh.num_vertices;
6796                 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6797                 if (wantnormals)
6798                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6799                 if (wanttangents)
6800                 {
6801                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6802                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6803                 }
6804                 if (!r_framedata_failed)
6805                 {
6806                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
6807                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
6808                 }
6809         }
6810         return !r_framedata_failed;
6811 }
6812
6813 void R_AnimCache_CacheVisibleEntities(void)
6814 {
6815         int i;
6816         qboolean wantnormals = true;
6817         qboolean wanttangents = !r_showsurfaces.integer;
6818
6819         switch(vid.renderpath)
6820         {
6821         case RENDERPATH_GL20:
6822         case RENDERPATH_CGGL:
6823                 break;
6824         case RENDERPATH_GL13:
6825         case RENDERPATH_GL11:
6826                 wanttangents = false;
6827                 break;
6828         }
6829
6830         if (r_shownormals.integer)
6831                 wanttangents = wantnormals = true;
6832
6833         // TODO: thread this
6834         // NOTE: R_PrepareRTLights() also caches entities
6835
6836         for (i = 0;i < r_refdef.scene.numentities;i++)
6837                 if (r_refdef.viewcache.entityvisible[i])
6838                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
6839 }
6840
6841 //==================================================================================
6842
6843 static void R_View_UpdateEntityLighting (void)
6844 {
6845         int i;
6846         entity_render_t *ent;
6847         vec3_t tempdiffusenormal, avg;
6848         vec_t f, fa, fd, fdd;
6849         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
6850
6851         for (i = 0;i < r_refdef.scene.numentities;i++)
6852         {
6853                 ent = r_refdef.scene.entities[i];
6854
6855                 // skip unseen models
6856                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
6857                         continue;
6858
6859                 // skip bsp models
6860                 if (ent->model && ent->model->brush.num_leafs)
6861                 {
6862                         // TODO: use modellight for r_ambient settings on world?
6863                         VectorSet(ent->modellight_ambient, 0, 0, 0);
6864                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
6865                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
6866                         continue;
6867                 }
6868
6869                 // fetch the lighting from the worldmodel data
6870                 VectorClear(ent->modellight_ambient);
6871                 VectorClear(ent->modellight_diffuse);
6872                 VectorClear(tempdiffusenormal);
6873                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
6874                 {
6875                         vec3_t org;
6876                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6877                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
6878                         if(ent->flags & RENDER_EQUALIZE)
6879                         {
6880                                 // first fix up ambient lighting...
6881                                 if(r_equalize_entities_minambient.value > 0)
6882                                 {
6883                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
6884                                         if(fd > 0)
6885                                         {
6886                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
6887                                                 if(fa < r_equalize_entities_minambient.value * fd)
6888                                                 {
6889                                                         // solve:
6890                                                         //   fa'/fd' = minambient
6891                                                         //   fa'+0.25*fd' = fa+0.25*fd
6892                                                         //   ...
6893                                                         //   fa' = fd' * minambient
6894                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
6895                                                         //   ...
6896                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
6897                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
6898                                                         //   ...
6899                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
6900                                                         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
6901                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
6902                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6903                                                 }
6904                                         }
6905                                 }
6906
6907                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
6908                                 {
6909                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
6910                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
6911                                         if(f > 0)
6912                                         {
6913                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
6914                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
6915                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6916                                         }
6917                                 }
6918                         }
6919                 }
6920                 else // highly rare
6921                         VectorSet(ent->modellight_ambient, 1, 1, 1);
6922
6923                 // move the light direction into modelspace coordinates for lighting code
6924                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
6925                 if(VectorLength2(ent->modellight_lightdir) == 0)
6926                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
6927                 VectorNormalize(ent->modellight_lightdir);
6928         }
6929 }
6930
6931 #define MAX_LINEOFSIGHTTRACES 64
6932
6933 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
6934 {
6935         int i;
6936         vec3_t boxmins, boxmaxs;
6937         vec3_t start;
6938         vec3_t end;
6939         dp_model_t *model = r_refdef.scene.worldmodel;
6940
6941         if (!model || !model->brush.TraceLineOfSight)
6942                 return true;
6943
6944         // expand the box a little
6945         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
6946         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
6947         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
6948         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
6949         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
6950         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
6951
6952         // return true if eye is inside enlarged box
6953         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
6954                 return true;
6955
6956         // try center
6957         VectorCopy(eye, start);
6958         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
6959         if (model->brush.TraceLineOfSight(model, start, end))
6960                 return true;
6961
6962         // try various random positions
6963         for (i = 0;i < numsamples;i++)
6964         {
6965                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
6966                 if (model->brush.TraceLineOfSight(model, start, end))
6967                         return true;
6968         }
6969
6970         return false;
6971 }
6972
6973
6974 static void R_View_UpdateEntityVisible (void)
6975 {
6976         int i;
6977         int renderimask;
6978         int samples;
6979         entity_render_t *ent;
6980
6981         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
6982                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
6983                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
6984                 :                                                          RENDER_EXTERIORMODEL;
6985         if (!r_drawviewmodel.integer)
6986                 renderimask |= RENDER_VIEWMODEL;
6987         if (!r_drawexteriormodel.integer)
6988                 renderimask |= RENDER_EXTERIORMODEL;
6989         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
6990         {
6991                 // worldmodel can check visibility
6992                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
6993                 for (i = 0;i < r_refdef.scene.numentities;i++)
6994                 {
6995                         ent = r_refdef.scene.entities[i];
6996                         if (!(ent->flags & renderimask))
6997                         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)))
6998                         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))
6999                                 r_refdef.viewcache.entityvisible[i] = true;
7000                 }
7001                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
7002                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
7003                 {
7004                         for (i = 0;i < r_refdef.scene.numentities;i++)
7005                         {
7006                                 ent = r_refdef.scene.entities[i];
7007                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
7008                                 {
7009                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
7010                                         if (samples < 0)
7011                                                 continue; // temp entities do pvs only
7012                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
7013                                                 ent->last_trace_visibility = realtime;
7014                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
7015                                                 r_refdef.viewcache.entityvisible[i] = 0;
7016                                 }
7017                         }
7018                 }
7019         }
7020         else
7021         {
7022                 // no worldmodel or it can't check visibility
7023                 for (i = 0;i < r_refdef.scene.numentities;i++)
7024                 {
7025                         ent = r_refdef.scene.entities[i];
7026                         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));
7027                 }
7028         }
7029 }
7030
7031 /// only used if skyrendermasked, and normally returns false
7032 int R_DrawBrushModelsSky (void)
7033 {
7034         int i, sky;
7035         entity_render_t *ent;
7036
7037         sky = false;
7038         for (i = 0;i < r_refdef.scene.numentities;i++)
7039         {
7040                 if (!r_refdef.viewcache.entityvisible[i])
7041                         continue;
7042                 ent = r_refdef.scene.entities[i];
7043                 if (!ent->model || !ent->model->DrawSky)
7044                         continue;
7045                 ent->model->DrawSky(ent);
7046                 sky = true;
7047         }
7048         return sky;
7049 }
7050
7051 static void R_DrawNoModel(entity_render_t *ent);
7052 static void R_DrawModels(void)
7053 {
7054         int i;
7055         entity_render_t *ent;
7056
7057         for (i = 0;i < r_refdef.scene.numentities;i++)
7058         {
7059                 if (!r_refdef.viewcache.entityvisible[i])
7060                         continue;
7061                 ent = r_refdef.scene.entities[i];
7062                 r_refdef.stats.entities++;
7063                 if (ent->model && ent->model->Draw != NULL)
7064                         ent->model->Draw(ent);
7065                 else
7066                         R_DrawNoModel(ent);
7067         }
7068 }
7069
7070 static void R_DrawModelsDepth(void)
7071 {
7072         int i;
7073         entity_render_t *ent;
7074
7075         for (i = 0;i < r_refdef.scene.numentities;i++)
7076         {
7077                 if (!r_refdef.viewcache.entityvisible[i])
7078                         continue;
7079                 ent = r_refdef.scene.entities[i];
7080                 if (ent->model && ent->model->DrawDepth != NULL)
7081                         ent->model->DrawDepth(ent);
7082         }
7083 }
7084
7085 static void R_DrawModelsDebug(void)
7086 {
7087         int i;
7088         entity_render_t *ent;
7089
7090         for (i = 0;i < r_refdef.scene.numentities;i++)
7091         {
7092                 if (!r_refdef.viewcache.entityvisible[i])
7093                         continue;
7094                 ent = r_refdef.scene.entities[i];
7095                 if (ent->model && ent->model->DrawDebug != NULL)
7096                         ent->model->DrawDebug(ent);
7097         }
7098 }
7099
7100 static void R_DrawModelsAddWaterPlanes(void)
7101 {
7102         int i;
7103         entity_render_t *ent;
7104
7105         for (i = 0;i < r_refdef.scene.numentities;i++)
7106         {
7107                 if (!r_refdef.viewcache.entityvisible[i])
7108                         continue;
7109                 ent = r_refdef.scene.entities[i];
7110                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
7111                         ent->model->DrawAddWaterPlanes(ent);
7112         }
7113 }
7114
7115 static void R_View_SetFrustum(void)
7116 {
7117         int i;
7118         double slopex, slopey;
7119         vec3_t forward, left, up, origin;
7120
7121         // we can't trust r_refdef.view.forward and friends in reflected scenes
7122         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
7123
7124 #if 0
7125         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
7126         r_refdef.view.frustum[0].normal[1] = 0 - 0;
7127         r_refdef.view.frustum[0].normal[2] = -1 - 0;
7128         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
7129         r_refdef.view.frustum[1].normal[1] = 0 + 0;
7130         r_refdef.view.frustum[1].normal[2] = -1 + 0;
7131         r_refdef.view.frustum[2].normal[0] = 0 - 0;
7132         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
7133         r_refdef.view.frustum[2].normal[2] = -1 - 0;
7134         r_refdef.view.frustum[3].normal[0] = 0 + 0;
7135         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
7136         r_refdef.view.frustum[3].normal[2] = -1 + 0;
7137 #endif
7138
7139 #if 0
7140         zNear = r_refdef.nearclip;
7141         nudge = 1.0 - 1.0 / (1<<23);
7142         r_refdef.view.frustum[4].normal[0] = 0 - 0;
7143         r_refdef.view.frustum[4].normal[1] = 0 - 0;
7144         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
7145         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
7146         r_refdef.view.frustum[5].normal[0] = 0 + 0;
7147         r_refdef.view.frustum[5].normal[1] = 0 + 0;
7148         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
7149         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
7150 #endif
7151
7152
7153
7154 #if 0
7155         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
7156         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
7157         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
7158         r_refdef.view.frustum[0].dist = m[15] - m[12];
7159
7160         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
7161         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
7162         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
7163         r_refdef.view.frustum[1].dist = m[15] + m[12];
7164
7165         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
7166         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
7167         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
7168         r_refdef.view.frustum[2].dist = m[15] - m[13];
7169
7170         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
7171         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
7172         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
7173         r_refdef.view.frustum[3].dist = m[15] + m[13];
7174
7175         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
7176         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
7177         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
7178         r_refdef.view.frustum[4].dist = m[15] - m[14];
7179
7180         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
7181         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
7182         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
7183         r_refdef.view.frustum[5].dist = m[15] + m[14];
7184 #endif
7185
7186         if (r_refdef.view.useperspective)
7187         {
7188                 slopex = 1.0 / r_refdef.view.frustum_x;
7189                 slopey = 1.0 / r_refdef.view.frustum_y;
7190                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
7191                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
7192                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
7193                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
7194                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7195
7196                 // Leaving those out was a mistake, those were in the old code, and they
7197                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
7198                 // I couldn't reproduce it after adding those normalizations. --blub
7199                 VectorNormalize(r_refdef.view.frustum[0].normal);
7200                 VectorNormalize(r_refdef.view.frustum[1].normal);
7201                 VectorNormalize(r_refdef.view.frustum[2].normal);
7202                 VectorNormalize(r_refdef.view.frustum[3].normal);
7203
7204                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
7205                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * r_refdef.view.frustum_x, left, -1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]);
7206                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward,  1024 * r_refdef.view.frustum_x, left, -1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[1]);
7207                 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]);
7208                 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]);
7209
7210                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
7211                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
7212                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
7213                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
7214                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7215         }
7216         else
7217         {
7218                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
7219                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
7220                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
7221                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
7222                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7223                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
7224                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
7225                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
7226                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
7227                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7228         }
7229         r_refdef.view.numfrustumplanes = 5;
7230
7231         if (r_refdef.view.useclipplane)
7232         {
7233                 r_refdef.view.numfrustumplanes = 6;
7234                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
7235         }
7236
7237         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7238                 PlaneClassify(r_refdef.view.frustum + i);
7239
7240         // LordHavoc: note to all quake engine coders, Quake had a special case
7241         // for 90 degrees which assumed a square view (wrong), so I removed it,
7242         // Quake2 has it disabled as well.
7243
7244         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
7245         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
7246         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
7247         //PlaneClassify(&frustum[0]);
7248
7249         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
7250         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
7251         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
7252         //PlaneClassify(&frustum[1]);
7253
7254         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
7255         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
7256         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
7257         //PlaneClassify(&frustum[2]);
7258
7259         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
7260         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
7261         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
7262         //PlaneClassify(&frustum[3]);
7263
7264         // nearclip plane
7265         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
7266         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
7267         //PlaneClassify(&frustum[4]);
7268 }
7269
7270 void R_View_Update(void)
7271 {
7272         R_Main_ResizeViewCache();
7273         R_View_SetFrustum();
7274         R_View_WorldVisibility(r_refdef.view.useclipplane);
7275         R_View_UpdateEntityVisible();
7276         R_View_UpdateEntityLighting();
7277 }
7278
7279 void R_SetupView(qboolean allowwaterclippingplane)
7280 {
7281         const float *customclipplane = NULL;
7282         float plane[4];
7283         if (r_refdef.view.useclipplane && allowwaterclippingplane)
7284         {
7285                 // LordHavoc: couldn't figure out how to make this approach the
7286                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
7287                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
7288                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
7289                         dist = r_refdef.view.clipplane.dist;
7290                 plane[0] = r_refdef.view.clipplane.normal[0];
7291                 plane[1] = r_refdef.view.clipplane.normal[1];
7292                 plane[2] = r_refdef.view.clipplane.normal[2];
7293                 plane[3] = dist;
7294                 customclipplane = plane;
7295         }
7296
7297         if (!r_refdef.view.useperspective)
7298                 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);
7299         else if (vid.stencil && r_useinfinitefarclip.integer)
7300                 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);
7301         else
7302                 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);
7303         R_SetViewport(&r_refdef.view.viewport);
7304 }
7305
7306 void R_EntityMatrix(const matrix4x4_t *matrix)
7307 {
7308         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
7309         {
7310                 gl_modelmatrixchanged = false;
7311                 gl_modelmatrix = *matrix;
7312                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
7313                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
7314                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
7315                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
7316                 CHECKGLERROR
7317                 switch(vid.renderpath)
7318                 {
7319                 case RENDERPATH_GL20:
7320                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
7321                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
7322                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7323                         break;
7324                 case RENDERPATH_CGGL:
7325 #ifdef SUPPORTCG
7326                         CHECKCGERROR
7327                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
7328                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
7329                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7330 #endif
7331                         break;
7332                 case RENDERPATH_GL13:
7333                 case RENDERPATH_GL11:
7334                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7335                         break;
7336                 }
7337         }
7338 }
7339
7340 void R_ResetViewRendering2D(void)
7341 {
7342         r_viewport_t viewport;
7343         DrawQ_Finish();
7344
7345         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
7346         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);
7347         R_SetViewport(&viewport);
7348         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
7349         GL_Color(1, 1, 1, 1);
7350         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7351         GL_BlendFunc(GL_ONE, GL_ZERO);
7352         GL_AlphaTest(false);
7353         GL_ScissorTest(false);
7354         GL_DepthMask(false);
7355         GL_DepthRange(0, 1);
7356         GL_DepthTest(false);
7357         R_EntityMatrix(&identitymatrix);
7358         R_Mesh_ResetTextureState();
7359         GL_PolygonOffset(0, 0);
7360         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7361         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7362         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7363         qglStencilMask(~0);CHECKGLERROR
7364         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7365         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7366         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
7367 }
7368
7369 void R_ResetViewRendering3D(void)
7370 {
7371         DrawQ_Finish();
7372
7373         R_SetupView(true);
7374         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7375         GL_Color(1, 1, 1, 1);
7376         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7377         GL_BlendFunc(GL_ONE, GL_ZERO);
7378         GL_AlphaTest(false);
7379         GL_ScissorTest(true);
7380         GL_DepthMask(true);
7381         GL_DepthRange(0, 1);
7382         GL_DepthTest(true);
7383         R_EntityMatrix(&identitymatrix);
7384         R_Mesh_ResetTextureState();
7385         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7386         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7387         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7388         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7389         qglStencilMask(~0);CHECKGLERROR
7390         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7391         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7392         GL_CullFace(r_refdef.view.cullface_back);
7393 }
7394
7395 /*
7396 ================
7397 R_RenderView_UpdateViewVectors
7398 ================
7399 */
7400 static void R_RenderView_UpdateViewVectors(void)
7401 {
7402         // break apart the view matrix into vectors for various purposes
7403         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
7404         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
7405         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
7406         VectorNegate(r_refdef.view.left, r_refdef.view.right);
7407         // make an inverted copy of the view matrix for tracking sprites
7408         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
7409 }
7410
7411 void R_RenderScene(void);
7412 void R_RenderWaterPlanes(void);
7413
7414 static void R_Water_StartFrame(void)
7415 {
7416         int i;
7417         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
7418         r_waterstate_waterplane_t *p;
7419
7420         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
7421                 return;
7422
7423         switch(vid.renderpath)
7424         {
7425         case RENDERPATH_GL20:
7426         case RENDERPATH_CGGL:
7427                 break;
7428         case RENDERPATH_GL13:
7429         case RENDERPATH_GL11:
7430                 return;
7431         }
7432
7433         // set waterwidth and waterheight to the water resolution that will be
7434         // used (often less than the screen resolution for faster rendering)
7435         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
7436         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
7437
7438         // calculate desired texture sizes
7439         // can't use water if the card does not support the texture size
7440         if (!r_water.integer || r_showsurfaces.integer)
7441                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
7442         else if (vid.support.arb_texture_non_power_of_two)
7443         {
7444                 texturewidth = waterwidth;
7445                 textureheight = waterheight;
7446                 camerawidth = waterwidth;
7447                 cameraheight = waterheight;
7448         }
7449         else
7450         {
7451                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
7452                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
7453                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
7454                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
7455         }
7456
7457         // allocate textures as needed
7458         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
7459         {
7460                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7461                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
7462                 {
7463                         if (p->texture_refraction)
7464                                 R_FreeTexture(p->texture_refraction);
7465                         p->texture_refraction = NULL;
7466                         if (p->texture_reflection)
7467                                 R_FreeTexture(p->texture_reflection);
7468                         p->texture_reflection = NULL;
7469                         if (p->texture_camera)
7470                                 R_FreeTexture(p->texture_camera);
7471                         p->texture_camera = NULL;
7472                 }
7473                 memset(&r_waterstate, 0, sizeof(r_waterstate));
7474                 r_waterstate.texturewidth = texturewidth;
7475                 r_waterstate.textureheight = textureheight;
7476                 r_waterstate.camerawidth = camerawidth;
7477                 r_waterstate.cameraheight = cameraheight;
7478         }
7479
7480         if (r_waterstate.texturewidth)
7481         {
7482                 r_waterstate.enabled = true;
7483
7484                 // when doing a reduced render (HDR) we want to use a smaller area
7485                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
7486                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
7487
7488                 // set up variables that will be used in shader setup
7489                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7490                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7491                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7492                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7493         }
7494
7495         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7496         r_waterstate.numwaterplanes = 0;
7497 }
7498
7499 void R_Water_AddWaterPlane(msurface_t *surface)
7500 {
7501         int triangleindex, planeindex;
7502         const int *e;
7503         vec3_t vert[3];
7504         vec3_t normal;
7505         vec3_t center;
7506         mplane_t plane;
7507         int cam_ent;
7508         r_waterstate_waterplane_t *p;
7509         texture_t *t = R_GetCurrentTexture(surface->texture);
7510         cam_ent = t->camera_entity;
7511         if(!(t->currentmaterialflags & MATERIALFLAG_CAMERA))
7512                 cam_ent = 0;
7513
7514         // just use the first triangle with a valid normal for any decisions
7515         VectorClear(normal);
7516         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
7517         {
7518                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
7519                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
7520                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
7521                 TriangleNormal(vert[0], vert[1], vert[2], normal);
7522                 if (VectorLength2(normal) >= 0.001)
7523                         break;
7524         }
7525
7526         VectorCopy(normal, plane.normal);
7527         VectorNormalize(plane.normal);
7528         plane.dist = DotProduct(vert[0], plane.normal);
7529         PlaneClassify(&plane);
7530         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
7531         {
7532                 // skip backfaces (except if nocullface is set)
7533                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
7534                         return;
7535                 VectorNegate(plane.normal, plane.normal);
7536                 plane.dist *= -1;
7537                 PlaneClassify(&plane);
7538         }
7539
7540
7541         // find a matching plane if there is one
7542         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7543                 if(p->camera_entity == t->camera_entity)
7544                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
7545                                 break;
7546         if (planeindex >= r_waterstate.maxwaterplanes)
7547                 return; // nothing we can do, out of planes
7548
7549         // if this triangle does not fit any known plane rendered this frame, add one
7550         if (planeindex >= r_waterstate.numwaterplanes)
7551         {
7552                 // store the new plane
7553                 r_waterstate.numwaterplanes++;
7554                 p->plane = plane;
7555                 // clear materialflags and pvs
7556                 p->materialflags = 0;
7557                 p->pvsvalid = false;
7558                 p->camera_entity = t->camera_entity;
7559         }
7560         // merge this surface's materialflags into the waterplane
7561         p->materialflags |= t->currentmaterialflags;
7562         if(!(p->materialflags & MATERIALFLAG_CAMERA))
7563         {
7564                 // merge this surface's PVS into the waterplane
7565                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
7566                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
7567                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
7568                 {
7569                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
7570                         p->pvsvalid = true;
7571                 }
7572         }
7573 }
7574
7575 static void R_Water_ProcessPlanes(void)
7576 {
7577         r_refdef_view_t originalview;
7578         r_refdef_view_t myview;
7579         int planeindex;
7580         r_waterstate_waterplane_t *p;
7581         vec3_t visorigin;
7582
7583         originalview = r_refdef.view;
7584
7585         // make sure enough textures are allocated
7586         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7587         {
7588                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7589                 {
7590                         if (!p->texture_refraction)
7591                                 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);
7592                         if (!p->texture_refraction)
7593                                 goto error;
7594                 }
7595                 else if (p->materialflags & MATERIALFLAG_CAMERA)
7596                 {
7597                         if (!p->texture_camera)
7598                                 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);
7599                         if (!p->texture_camera)
7600                                 goto error;
7601                 }
7602
7603                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7604                 {
7605                         if (!p->texture_reflection)
7606                                 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);
7607                         if (!p->texture_reflection)
7608                                 goto error;
7609                 }
7610         }
7611
7612         // render views
7613         r_refdef.view = originalview;
7614         r_refdef.view.showdebug = false;
7615         r_refdef.view.width = r_waterstate.waterwidth;
7616         r_refdef.view.height = r_waterstate.waterheight;
7617         r_refdef.view.useclipplane = true;
7618         myview = r_refdef.view;
7619         r_waterstate.renderingscene = true;
7620         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7621         {
7622                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7623                 {
7624                         r_refdef.view = myview;
7625                         // render reflected scene and copy into texture
7626                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
7627                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
7628                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
7629                         r_refdef.view.clipplane = p->plane;
7630                         // reverse the cullface settings for this render
7631                         r_refdef.view.cullface_front = GL_FRONT;
7632                         r_refdef.view.cullface_back = GL_BACK;
7633                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
7634                         {
7635                                 r_refdef.view.usecustompvs = true;
7636                                 if (p->pvsvalid)
7637                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7638                                 else
7639                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7640                         }
7641
7642                         R_ResetViewRendering3D();
7643                         R_ClearScreen(r_refdef.fogenabled);
7644                         R_View_Update();
7645                         R_RenderScene();
7646
7647                         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);
7648                 }
7649
7650                 // render the normal view scene and copy into texture
7651                 // (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)
7652                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7653                 {
7654                         r_waterstate.renderingrefraction = true;
7655                         r_refdef.view = myview;
7656
7657                         r_refdef.view.clipplane = p->plane;
7658                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
7659                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
7660
7661                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
7662                         {
7663                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
7664                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
7665                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
7666                                 R_RenderView_UpdateViewVectors();
7667                                 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);
7668                         }
7669
7670                         PlaneClassify(&r_refdef.view.clipplane);
7671
7672                         R_ResetViewRendering3D();
7673                         R_ClearScreen(r_refdef.fogenabled);
7674                         R_View_Update();
7675                         R_RenderScene();
7676
7677                         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);
7678                         r_waterstate.renderingrefraction = false;
7679                 }
7680                 else if (p->materialflags & MATERIALFLAG_CAMERA)
7681                 {
7682                         r_refdef.view = myview;
7683
7684                         r_refdef.view.clipplane = p->plane;
7685                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
7686                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
7687
7688                         r_refdef.view.width = r_waterstate.camerawidth;
7689                         r_refdef.view.height = r_waterstate.cameraheight;
7690                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
7691                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
7692
7693                         if(p->camera_entity)
7694                         {
7695                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
7696                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
7697                         }
7698
7699                         // reverse the cullface settings for this render
7700                         r_refdef.view.cullface_front = GL_FRONT;
7701                         r_refdef.view.cullface_back = GL_BACK;
7702                         // also reverse the view matrix
7703                         Matrix4x4_ConcatScale3(&r_refdef.view.matrix, 1, -1, 1);
7704                         R_RenderView_UpdateViewVectors();
7705                         if(p->camera_entity)
7706                                 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);
7707                         
7708                         // camera needs no clipplane
7709                         r_refdef.view.useclipplane = false;
7710
7711                         PlaneClassify(&r_refdef.view.clipplane);
7712
7713                         R_ResetViewRendering3D();
7714                         R_ClearScreen(r_refdef.fogenabled);
7715                         R_View_Update();
7716                         R_RenderScene();
7717
7718                         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);
7719                         r_waterstate.renderingrefraction = false;
7720                 }
7721
7722         }
7723         r_waterstate.renderingscene = false;
7724         r_refdef.view = originalview;
7725         R_ResetViewRendering3D();
7726         R_ClearScreen(r_refdef.fogenabled);
7727         R_View_Update();
7728         return;
7729 error:
7730         r_refdef.view = originalview;
7731         r_waterstate.renderingscene = false;
7732         Cvar_SetValueQuick(&r_water, 0);
7733         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
7734         return;
7735 }
7736
7737 void R_Bloom_StartFrame(void)
7738 {
7739         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
7740
7741         switch(vid.renderpath)
7742         {
7743         case RENDERPATH_GL20:
7744         case RENDERPATH_CGGL:
7745                 break;
7746         case RENDERPATH_GL13:
7747         case RENDERPATH_GL11:
7748                 return;
7749         }
7750
7751         // set bloomwidth and bloomheight to the bloom resolution that will be
7752         // used (often less than the screen resolution for faster rendering)
7753         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
7754         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
7755         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
7756         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
7757         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
7758
7759         // calculate desired texture sizes
7760         if (vid.support.arb_texture_non_power_of_two)
7761         {
7762                 screentexturewidth = r_refdef.view.width;
7763                 screentextureheight = r_refdef.view.height;
7764                 bloomtexturewidth = r_bloomstate.bloomwidth;
7765                 bloomtextureheight = r_bloomstate.bloomheight;
7766         }
7767         else
7768         {
7769                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
7770                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
7771                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
7772                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
7773         }
7774
7775         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))
7776         {
7777                 Cvar_SetValueQuick(&r_hdr, 0);
7778                 Cvar_SetValueQuick(&r_bloom, 0);
7779                 Cvar_SetValueQuick(&r_motionblur, 0);
7780                 Cvar_SetValueQuick(&r_damageblur, 0);
7781         }
7782
7783         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)))
7784                 screentexturewidth = screentextureheight = 0;
7785         if (!r_hdr.integer && !r_bloom.integer)
7786                 bloomtexturewidth = bloomtextureheight = 0;
7787
7788         // allocate textures as needed
7789         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
7790         {
7791                 if (r_bloomstate.texture_screen)
7792                         R_FreeTexture(r_bloomstate.texture_screen);
7793                 r_bloomstate.texture_screen = NULL;
7794                 r_bloomstate.screentexturewidth = screentexturewidth;
7795                 r_bloomstate.screentextureheight = screentextureheight;
7796                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
7797                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
7798         }
7799         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
7800         {
7801                 if (r_bloomstate.texture_bloom)
7802                         R_FreeTexture(r_bloomstate.texture_bloom);
7803                 r_bloomstate.texture_bloom = NULL;
7804                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
7805                 r_bloomstate.bloomtextureheight = bloomtextureheight;
7806                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
7807                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7808         }
7809
7810         // when doing a reduced render (HDR) we want to use a smaller area
7811         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
7812         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
7813         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
7814         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
7815         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
7816
7817         // set up a texcoord array for the full resolution screen image
7818         // (we have to keep this around to copy back during final render)
7819         r_bloomstate.screentexcoord2f[0] = 0;
7820         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7821         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7822         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7823         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7824         r_bloomstate.screentexcoord2f[5] = 0;
7825         r_bloomstate.screentexcoord2f[6] = 0;
7826         r_bloomstate.screentexcoord2f[7] = 0;
7827
7828         // set up a texcoord array for the reduced resolution bloom image
7829         // (which will be additive blended over the screen image)
7830         r_bloomstate.bloomtexcoord2f[0] = 0;
7831         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7832         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7833         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7834         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7835         r_bloomstate.bloomtexcoord2f[5] = 0;
7836         r_bloomstate.bloomtexcoord2f[6] = 0;
7837         r_bloomstate.bloomtexcoord2f[7] = 0;
7838
7839         if (r_hdr.integer || r_bloom.integer)
7840         {
7841                 r_bloomstate.enabled = true;
7842                 r_bloomstate.hdr = r_hdr.integer != 0;
7843         }
7844
7845         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);
7846 }
7847
7848 void R_Bloom_CopyBloomTexture(float colorscale)
7849 {
7850         r_refdef.stats.bloom++;
7851
7852         // scale down screen texture to the bloom texture size
7853         CHECKGLERROR
7854         R_SetViewport(&r_bloomstate.viewport);
7855         GL_BlendFunc(GL_ONE, GL_ZERO);
7856         GL_Color(colorscale, colorscale, colorscale, 1);
7857         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
7858         // TODO: do boxfilter scale-down in shader?
7859         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7860         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
7861         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7862
7863         // we now have a bloom image in the framebuffer
7864         // copy it into the bloom image texture for later processing
7865         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);
7866         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7867 }
7868
7869 void R_Bloom_CopyHDRTexture(void)
7870 {
7871         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);
7872         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7873 }
7874
7875 void R_Bloom_MakeTexture(void)
7876 {
7877         int x, range, dir;
7878         float xoffset, yoffset, r, brighten;
7879
7880         r_refdef.stats.bloom++;
7881
7882         R_ResetViewRendering2D();
7883
7884         // we have a bloom image in the framebuffer
7885         CHECKGLERROR
7886         R_SetViewport(&r_bloomstate.viewport);
7887
7888         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
7889         {
7890                 x *= 2;
7891                 r = bound(0, r_bloom_colorexponent.value / x, 1);
7892                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7893                 GL_Color(r,r,r,1);
7894                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
7895                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7896                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
7897                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7898
7899                 // copy the vertically blurred bloom view to a texture
7900                 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
7901                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7902         }
7903
7904         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
7905         brighten = r_bloom_brighten.value;
7906         if (r_hdr.integer)
7907                 brighten *= r_hdr_range.value;
7908         brighten = sqrt(brighten);
7909         if(range >= 1)
7910                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
7911         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7912
7913         for (dir = 0;dir < 2;dir++)
7914         {
7915                 // blend on at multiple vertical offsets to achieve a vertical blur
7916                 // TODO: do offset blends using GLSL
7917                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
7918                 GL_BlendFunc(GL_ONE, GL_ZERO);
7919                 for (x = -range;x <= range;x++)
7920                 {
7921                         if (!dir){xoffset = 0;yoffset = x;}
7922                         else {xoffset = x;yoffset = 0;}
7923                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
7924                         yoffset /= (float)r_bloomstate.bloomtextureheight;
7925                         // compute a texcoord array with the specified x and y offset
7926                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
7927                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7928                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7929                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7930                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7931                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
7932                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
7933                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
7934                         // this r value looks like a 'dot' particle, fading sharply to
7935                         // black at the edges
7936                         // (probably not realistic but looks good enough)
7937                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
7938                         //r = brighten/(range*2+1);
7939                         r = brighten / (range * 2 + 1);
7940                         if(range >= 1)
7941                                 r *= (1 - x*x/(float)(range*range));
7942                         GL_Color(r, r, r, 1);
7943                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
7944                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
7945                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7946                         GL_BlendFunc(GL_ONE, GL_ONE);
7947                 }
7948
7949                 // copy the vertically blurred bloom view to a texture
7950                 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
7951                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7952         }
7953
7954         // apply subtract last
7955         // (just like it would be in a GLSL shader)
7956         if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
7957         {
7958                 GL_BlendFunc(GL_ONE, GL_ZERO);
7959                 GL_Color(1,1,1,1);
7960                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
7961                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7962                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
7963                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7964
7965                 GL_BlendFunc(GL_ONE, GL_ONE);
7966                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
7967                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7968                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
7969                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
7970                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
7971                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7972                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
7973
7974                 // copy the darkened bloom view to a texture
7975                 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
7976                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7977         }
7978 }
7979
7980 void R_HDR_RenderBloomTexture(void)
7981 {
7982         int oldwidth, oldheight;
7983         float oldcolorscale;
7984
7985         oldcolorscale = r_refdef.view.colorscale;
7986         oldwidth = r_refdef.view.width;
7987         oldheight = r_refdef.view.height;
7988         r_refdef.view.width = r_bloomstate.bloomwidth;
7989         r_refdef.view.height = r_bloomstate.bloomheight;
7990
7991         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
7992         // TODO: add exposure compensation features
7993         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
7994
7995         r_refdef.view.showdebug = false;
7996         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
7997
7998         R_ResetViewRendering3D();
7999
8000         R_ClearScreen(r_refdef.fogenabled);
8001         if (r_timereport_active)
8002                 R_TimeReport("HDRclear");
8003
8004         R_View_Update();
8005         if (r_timereport_active)
8006                 R_TimeReport("visibility");
8007
8008         // only do secondary renders with HDR if r_hdr is 2 or higher
8009         r_waterstate.numwaterplanes = 0;
8010         if (r_waterstate.enabled && r_hdr.integer >= 2)
8011                 R_RenderWaterPlanes();
8012
8013         r_refdef.view.showdebug = true;
8014         R_RenderScene();
8015         r_waterstate.numwaterplanes = 0;
8016
8017         R_ResetViewRendering2D();
8018
8019         R_Bloom_CopyHDRTexture();
8020         R_Bloom_MakeTexture();
8021
8022         // restore the view settings
8023         r_refdef.view.width = oldwidth;
8024         r_refdef.view.height = oldheight;
8025         r_refdef.view.colorscale = oldcolorscale;
8026
8027         R_ResetViewRendering3D();
8028
8029         R_ClearScreen(r_refdef.fogenabled);
8030         if (r_timereport_active)
8031                 R_TimeReport("viewclear");
8032 }
8033
8034 static void R_BlendView(void)
8035 {
8036         unsigned int permutation;
8037         float uservecs[4][4];
8038
8039         switch (vid.renderpath)
8040         {
8041         case RENDERPATH_GL20:
8042         case RENDERPATH_CGGL:
8043                 permutation =
8044                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
8045                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
8046                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
8047                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
8048                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
8049
8050                 if (r_bloomstate.texture_screen)
8051                 {
8052                         // make sure the buffer is available
8053                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
8054
8055                         R_ResetViewRendering2D();
8056
8057                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
8058                         {
8059                                 // declare variables
8060                                 float speed;
8061                                 static float avgspeed;
8062
8063                                 speed = VectorLength(cl.movement_velocity);
8064
8065                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
8066                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
8067
8068                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
8069                                 speed = bound(0, speed, 1);
8070                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
8071
8072                                 // calculate values into a standard alpha
8073                                 cl.motionbluralpha = 1 - exp(-
8074                                                 (
8075                                                  (r_motionblur.value * speed / 80)
8076                                                  +
8077                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
8078                                                 )
8079                                                 /
8080                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
8081                                            );
8082
8083                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
8084                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
8085                                 // apply the blur
8086                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
8087                                 {
8088                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8089                                         GL_Color(1, 1, 1, cl.motionbluralpha);
8090                                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8091                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8092                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8093                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8094                                 }
8095                         }
8096
8097                         // copy view into the screen texture
8098                         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);
8099                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8100                 }
8101                 else if (!r_bloomstate.texture_bloom)
8102                 {
8103                         // we may still have to do view tint...
8104                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8105                         {
8106                                 // apply a color tint to the whole view
8107                                 R_ResetViewRendering2D();
8108                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8109                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
8110                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8111                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8112                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8113                         }
8114                         break; // no screen processing, no bloom, skip it
8115                 }
8116
8117                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
8118                 {
8119                         // render simple bloom effect
8120                         // copy the screen and shrink it and darken it for the bloom process
8121                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
8122                         // make the bloom texture
8123                         R_Bloom_MakeTexture();
8124                 }
8125
8126 #if _MSC_VER >= 1400
8127 #define sscanf sscanf_s
8128 #endif
8129                 memset(uservecs, 0, sizeof(uservecs));
8130                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
8131                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
8132                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
8133                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
8134
8135                 R_ResetViewRendering2D();
8136                 GL_Color(1, 1, 1, 1);
8137                 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8138                 GL_BlendFunc(GL_ONE, GL_ZERO);
8139
8140                 switch(vid.renderpath)
8141                 {
8142                 case RENDERPATH_GL20:
8143                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
8144                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
8145                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
8146                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
8147                         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]);
8148                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8149                         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]);
8150                         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]);
8151                         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]);
8152                         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]);
8153 //                      if (r_glsl_permutation->loc_UseSobel           >= 0) qglUniform1fARB(r_glsl_permutation->loc_UseSobel       , r_glsl_postprocess_sobel.value);
8154                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
8155                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
8156                         break;
8157                 case RENDERPATH_CGGL:
8158 #ifdef SUPPORTCG
8159                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
8160                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
8161                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
8162                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
8163                         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
8164                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
8165                         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
8166                         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
8167                         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
8168                         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
8169 //                      if (r_cg_permutation->fp_UseSobel          ) cgGLSetParameter1f(     r_cg_permutation->fp_UseSobel          , r_glsl_postprocess_sobel.value);CHECKCGERROR
8170                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
8171                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
8172 #endif
8173                         break;
8174                 default:
8175                         break;
8176                 }
8177                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8178                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8179                 break;
8180         case RENDERPATH_GL13:
8181         case RENDERPATH_GL11:
8182                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8183                 {
8184                         // apply a color tint to the whole view
8185                         R_ResetViewRendering2D();
8186                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8187                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
8188                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8189                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8190                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8191                 }
8192                 break;
8193         }
8194 }
8195
8196 matrix4x4_t r_waterscrollmatrix;
8197
8198 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
8199 {
8200         if (r_refdef.fog_density)
8201         {
8202                 r_refdef.fogcolor[0] = r_refdef.fog_red;
8203                 r_refdef.fogcolor[1] = r_refdef.fog_green;
8204                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
8205
8206                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
8207                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
8208                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
8209                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
8210
8211                 {
8212                         vec3_t fogvec;
8213                         VectorCopy(r_refdef.fogcolor, fogvec);
8214                         //   color.rgb *= ContrastBoost * SceneBrightness;
8215                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
8216                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
8217                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
8218                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
8219                 }
8220         }
8221 }
8222
8223 void R_UpdateVariables(void)
8224 {
8225         R_Textures_Frame();
8226
8227         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
8228
8229         r_refdef.farclip = r_farclip_base.value;
8230         if (r_refdef.scene.worldmodel)
8231                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
8232         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
8233
8234         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
8235                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
8236         r_refdef.polygonfactor = 0;
8237         r_refdef.polygonoffset = 0;
8238         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8239         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8240
8241         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
8242         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
8243         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
8244         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
8245         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
8246         if (r_showsurfaces.integer)
8247         {
8248                 r_refdef.scene.rtworld = false;
8249                 r_refdef.scene.rtworldshadows = false;
8250                 r_refdef.scene.rtdlight = false;
8251                 r_refdef.scene.rtdlightshadows = false;
8252                 r_refdef.lightmapintensity = 0;
8253         }
8254
8255         if (gamemode == GAME_NEHAHRA)
8256         {
8257                 if (gl_fogenable.integer)
8258                 {
8259                         r_refdef.oldgl_fogenable = true;
8260                         r_refdef.fog_density = gl_fogdensity.value;
8261                         r_refdef.fog_red = gl_fogred.value;
8262                         r_refdef.fog_green = gl_foggreen.value;
8263                         r_refdef.fog_blue = gl_fogblue.value;
8264                         r_refdef.fog_alpha = 1;
8265                         r_refdef.fog_start = 0;
8266                         r_refdef.fog_end = gl_skyclip.value;
8267                         r_refdef.fog_height = 1<<30;
8268                         r_refdef.fog_fadedepth = 128;
8269                 }
8270                 else if (r_refdef.oldgl_fogenable)
8271                 {
8272                         r_refdef.oldgl_fogenable = false;
8273                         r_refdef.fog_density = 0;
8274                         r_refdef.fog_red = 0;
8275                         r_refdef.fog_green = 0;
8276                         r_refdef.fog_blue = 0;
8277                         r_refdef.fog_alpha = 0;
8278                         r_refdef.fog_start = 0;
8279                         r_refdef.fog_end = 0;
8280                         r_refdef.fog_height = 1<<30;
8281                         r_refdef.fog_fadedepth = 128;
8282                 }
8283         }
8284
8285         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
8286         r_refdef.fog_start = max(0, r_refdef.fog_start);
8287         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
8288
8289         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
8290
8291         if (r_refdef.fog_density && r_drawfog.integer)
8292         {
8293                 r_refdef.fogenabled = true;
8294                 // this is the point where the fog reaches 0.9986 alpha, which we
8295                 // consider a good enough cutoff point for the texture
8296                 // (0.9986 * 256 == 255.6)
8297                 if (r_fog_exp2.integer)
8298                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
8299                 else
8300                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
8301                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
8302                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
8303                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
8304                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
8305                         R_BuildFogHeightTexture();
8306                 // fog color was already set
8307                 // update the fog texture
8308                 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)
8309                         R_BuildFogTexture();
8310                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
8311                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
8312         }
8313         else
8314                 r_refdef.fogenabled = false;
8315
8316         switch(vid.renderpath)
8317         {
8318         case RENDERPATH_GL20:
8319         case RENDERPATH_CGGL:
8320                 if(v_glslgamma.integer && !vid_gammatables_trivial)
8321                 {
8322                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
8323                         {
8324                                 // build GLSL gamma texture
8325 #define RAMPWIDTH 256
8326                                 unsigned short ramp[RAMPWIDTH * 3];
8327                                 unsigned char rampbgr[RAMPWIDTH][4];
8328                                 int i;
8329
8330                                 r_texture_gammaramps_serial = vid_gammatables_serial;
8331
8332                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
8333                                 for(i = 0; i < RAMPWIDTH; ++i)
8334                                 {
8335                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8336                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8337                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
8338                                         rampbgr[i][3] = 0;
8339                                 }
8340                                 if (r_texture_gammaramps)
8341                                 {
8342                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
8343                                 }
8344                                 else
8345                                 {
8346                                         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);
8347                                 }
8348                         }
8349                 }
8350                 else
8351                 {
8352                         // remove GLSL gamma texture
8353                 }
8354                 break;
8355         case RENDERPATH_GL13:
8356         case RENDERPATH_GL11:
8357                 break;
8358         }
8359 }
8360
8361 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
8362 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
8363 /*
8364 ================
8365 R_SelectScene
8366 ================
8367 */
8368 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
8369         if( scenetype != r_currentscenetype ) {
8370                 // store the old scenetype
8371                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
8372                 r_currentscenetype = scenetype;
8373                 // move in the new scene
8374                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
8375         }
8376 }
8377
8378 /*
8379 ================
8380 R_GetScenePointer
8381 ================
8382 */
8383 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
8384 {
8385         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
8386         if( scenetype == r_currentscenetype ) {
8387                 return &r_refdef.scene;
8388         } else {
8389                 return &r_scenes_store[ scenetype ];
8390         }
8391 }
8392
8393 /*
8394 ================
8395 R_RenderView
8396 ================
8397 */
8398 void R_RenderView(void)
8399 {
8400         if (r_timereport_active)
8401                 R_TimeReport("start");
8402         r_textureframe++; // used only by R_GetCurrentTexture
8403         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8404
8405         if (!r_drawentities.integer)
8406                 r_refdef.scene.numentities = 0;
8407
8408         R_AnimCache_ClearCache();
8409         R_FrameData_NewFrame();
8410
8411         if (r_refdef.view.isoverlay)
8412         {
8413                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
8414                 GL_Clear( GL_DEPTH_BUFFER_BIT );
8415                 R_TimeReport("depthclear");
8416
8417                 r_refdef.view.showdebug = false;
8418
8419                 r_waterstate.enabled = false;
8420                 r_waterstate.numwaterplanes = 0;
8421
8422                 R_RenderScene();
8423
8424                 CHECKGLERROR
8425                 return;
8426         }
8427
8428         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
8429                 return; //Host_Error ("R_RenderView: NULL worldmodel");
8430
8431         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
8432
8433         R_RenderView_UpdateViewVectors();
8434
8435         R_Shadow_UpdateWorldLightSelection();
8436
8437         R_Bloom_StartFrame();
8438         R_Water_StartFrame();
8439
8440         CHECKGLERROR
8441         if (r_timereport_active)
8442                 R_TimeReport("viewsetup");
8443
8444         R_ResetViewRendering3D();
8445
8446         if (r_refdef.view.clear || r_refdef.fogenabled)
8447         {
8448                 R_ClearScreen(r_refdef.fogenabled);
8449                 if (r_timereport_active)
8450                         R_TimeReport("viewclear");
8451         }
8452         r_refdef.view.clear = true;
8453
8454         // this produces a bloom texture to be used in R_BlendView() later
8455         if (r_hdr.integer && r_bloomstate.bloomwidth)
8456         {
8457                 R_HDR_RenderBloomTexture();
8458                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
8459                 r_textureframe++; // used only by R_GetCurrentTexture
8460         }
8461
8462         r_refdef.view.showdebug = true;
8463
8464         R_View_Update();
8465         if (r_timereport_active)
8466                 R_TimeReport("visibility");
8467
8468         r_waterstate.numwaterplanes = 0;
8469         if (r_waterstate.enabled)
8470                 R_RenderWaterPlanes();
8471
8472         R_RenderScene();
8473         r_waterstate.numwaterplanes = 0;
8474
8475         R_BlendView();
8476         if (r_timereport_active)
8477                 R_TimeReport("blendview");
8478
8479         GL_Scissor(0, 0, vid.width, vid.height);
8480         GL_ScissorTest(false);
8481         CHECKGLERROR
8482 }
8483
8484 void R_RenderWaterPlanes(void)
8485 {
8486         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
8487         {
8488                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
8489                 if (r_timereport_active)
8490                         R_TimeReport("waterworld");
8491         }
8492
8493         // don't let sound skip if going slow
8494         if (r_refdef.scene.extraupdate)
8495                 S_ExtraUpdate ();
8496
8497         R_DrawModelsAddWaterPlanes();
8498         if (r_timereport_active)
8499                 R_TimeReport("watermodels");
8500
8501         if (r_waterstate.numwaterplanes)
8502         {
8503                 R_Water_ProcessPlanes();
8504                 if (r_timereport_active)
8505                         R_TimeReport("waterscenes");
8506         }
8507 }
8508
8509 extern void R_DrawLightningBeams (void);
8510 extern void VM_CL_AddPolygonsToMeshQueue (void);
8511 extern void R_DrawPortals (void);
8512 extern cvar_t cl_locs_show;
8513 static void R_DrawLocs(void);
8514 static void R_DrawEntityBBoxes(void);
8515 static void R_DrawModelDecals(void);
8516 extern void R_DrawModelShadows(void);
8517 extern void R_DrawModelShadowMaps(void);
8518 extern cvar_t cl_decals_newsystem;
8519 extern qboolean r_shadow_usingdeferredprepass;
8520 void R_RenderScene(void)
8521 {
8522         qboolean shadowmapping = false;
8523
8524         if (r_timereport_active)
8525                 R_TimeReport("beginscene");
8526
8527         r_refdef.stats.renders++;
8528
8529         R_UpdateFogColor();
8530
8531         // don't let sound skip if going slow
8532         if (r_refdef.scene.extraupdate)
8533                 S_ExtraUpdate ();
8534
8535         R_MeshQueue_BeginScene();
8536
8537         R_SkyStartFrame();
8538
8539         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);
8540
8541         if (r_timereport_active)
8542                 R_TimeReport("skystartframe");
8543
8544         if (cl.csqc_vidvars.drawworld)
8545         {
8546                 // don't let sound skip if going slow
8547                 if (r_refdef.scene.extraupdate)
8548                         S_ExtraUpdate ();
8549
8550                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
8551                 {
8552                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
8553                         if (r_timereport_active)
8554                                 R_TimeReport("worldsky");
8555                 }
8556
8557                 if (R_DrawBrushModelsSky() && r_timereport_active)
8558                         R_TimeReport("bmodelsky");
8559
8560                 if (skyrendermasked && skyrenderlater)
8561                 {
8562                         // we have to force off the water clipping plane while rendering sky
8563                         R_SetupView(false);
8564                         R_Sky();
8565                         R_SetupView(true);
8566                         if (r_timereport_active)
8567                                 R_TimeReport("sky");
8568                 }
8569         }
8570
8571         R_AnimCache_CacheVisibleEntities();
8572         if (r_timereport_active)
8573                 R_TimeReport("animation");
8574
8575         R_Shadow_PrepareLights();
8576         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
8577                 R_Shadow_PrepareModelShadows();
8578         if (r_timereport_active)
8579                 R_TimeReport("preparelights");
8580
8581         if (R_Shadow_ShadowMappingEnabled())
8582                 shadowmapping = true;
8583
8584         if (r_shadow_usingdeferredprepass)
8585                 R_Shadow_DrawPrepass();
8586
8587         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
8588         {
8589                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
8590                 if (r_timereport_active)
8591                         R_TimeReport("worlddepth");
8592         }
8593         if (r_depthfirst.integer >= 2)
8594         {
8595                 R_DrawModelsDepth();
8596                 if (r_timereport_active)
8597                         R_TimeReport("modeldepth");
8598         }
8599
8600         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
8601         {
8602                 R_DrawModelShadowMaps();
8603                 R_ResetViewRendering3D();
8604                 // don't let sound skip if going slow
8605                 if (r_refdef.scene.extraupdate)
8606                         S_ExtraUpdate ();
8607         }
8608
8609         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
8610         {
8611                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
8612                 if (r_timereport_active)
8613                         R_TimeReport("world");
8614         }
8615
8616         // don't let sound skip if going slow
8617         if (r_refdef.scene.extraupdate)
8618                 S_ExtraUpdate ();
8619
8620         R_DrawModels();
8621         if (r_timereport_active)
8622                 R_TimeReport("models");
8623
8624         // don't let sound skip if going slow
8625         if (r_refdef.scene.extraupdate)
8626                 S_ExtraUpdate ();
8627
8628         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8629         {
8630                 R_DrawModelShadows();
8631                 R_ResetViewRendering3D();
8632                 // don't let sound skip if going slow
8633                 if (r_refdef.scene.extraupdate)
8634                         S_ExtraUpdate ();
8635         }
8636
8637         if (!r_shadow_usingdeferredprepass)
8638         {
8639                 R_Shadow_DrawLights();
8640                 if (r_timereport_active)
8641                         R_TimeReport("rtlights");
8642         }
8643
8644         // don't let sound skip if going slow
8645         if (r_refdef.scene.extraupdate)
8646                 S_ExtraUpdate ();
8647
8648         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8649         {
8650                 R_DrawModelShadows();
8651                 R_ResetViewRendering3D();
8652                 // don't let sound skip if going slow
8653                 if (r_refdef.scene.extraupdate)
8654                         S_ExtraUpdate ();
8655         }
8656
8657         if (cl.csqc_vidvars.drawworld)
8658         {
8659                 if (cl_decals_newsystem.integer)
8660                 {
8661                         R_DrawModelDecals();
8662                         if (r_timereport_active)
8663                                 R_TimeReport("modeldecals");
8664                 }
8665                 else
8666                 {
8667                         R_DrawDecals();
8668                         if (r_timereport_active)
8669                                 R_TimeReport("decals");
8670                 }
8671
8672                 R_DrawParticles();
8673                 if (r_timereport_active)
8674                         R_TimeReport("particles");
8675
8676                 R_DrawExplosions();
8677                 if (r_timereport_active)
8678                         R_TimeReport("explosions");
8679
8680                 R_DrawLightningBeams();
8681                 if (r_timereport_active)
8682                         R_TimeReport("lightning");
8683         }
8684
8685         VM_CL_AddPolygonsToMeshQueue();
8686
8687         if (r_refdef.view.showdebug)
8688         {
8689                 if (cl_locs_show.integer)
8690                 {
8691                         R_DrawLocs();
8692                         if (r_timereport_active)
8693                                 R_TimeReport("showlocs");
8694                 }
8695
8696                 if (r_drawportals.integer)
8697                 {
8698                         R_DrawPortals();
8699                         if (r_timereport_active)
8700                                 R_TimeReport("portals");
8701                 }
8702
8703                 if (r_showbboxes.value > 0)
8704                 {
8705                         R_DrawEntityBBoxes();
8706                         if (r_timereport_active)
8707                                 R_TimeReport("bboxes");
8708                 }
8709         }
8710
8711         R_MeshQueue_RenderTransparent();
8712         if (r_timereport_active)
8713                 R_TimeReport("drawtrans");
8714
8715         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))
8716         {
8717                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
8718                 if (r_timereport_active)
8719                         R_TimeReport("worlddebug");
8720                 R_DrawModelsDebug();
8721                 if (r_timereport_active)
8722                         R_TimeReport("modeldebug");
8723         }
8724
8725         if (cl.csqc_vidvars.drawworld)
8726         {
8727                 R_Shadow_DrawCoronas();
8728                 if (r_timereport_active)
8729                         R_TimeReport("coronas");
8730         }
8731
8732         // don't let sound skip if going slow
8733         if (r_refdef.scene.extraupdate)
8734                 S_ExtraUpdate ();
8735
8736         R_ResetViewRendering2D();
8737 }
8738
8739 static const unsigned short bboxelements[36] =
8740 {
8741         5, 1, 3, 5, 3, 7,
8742         6, 2, 0, 6, 0, 4,
8743         7, 3, 2, 7, 2, 6,
8744         4, 0, 1, 4, 1, 5,
8745         4, 5, 7, 4, 7, 6,
8746         1, 0, 2, 1, 2, 3,
8747 };
8748
8749 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
8750 {
8751         int i;
8752         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
8753
8754         RSurf_ActiveWorldEntity();
8755
8756         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8757         GL_DepthMask(false);
8758         GL_DepthRange(0, 1);
8759         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8760         R_Mesh_ResetTextureState();
8761
8762         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
8763         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
8764         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
8765         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
8766         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
8767         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
8768         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
8769         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
8770         R_FillColors(color4f, 8, cr, cg, cb, ca);
8771         if (r_refdef.fogenabled)
8772         {
8773                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
8774                 {
8775                         f1 = RSurf_FogVertex(v);
8776                         f2 = 1 - f1;
8777                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
8778                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
8779                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
8780                 }
8781         }
8782         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
8783         R_Mesh_ResetTextureState();
8784         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8785         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
8786 }
8787
8788 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8789 {
8790         int i;
8791         float color[4];
8792         prvm_edict_t *edict;
8793         prvm_prog_t *prog_save = prog;
8794
8795         // this function draws bounding boxes of server entities
8796         if (!sv.active)
8797                 return;
8798
8799         GL_CullFace(GL_NONE);
8800         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8801
8802         prog = 0;
8803         SV_VM_Begin();
8804         for (i = 0;i < numsurfaces;i++)
8805         {
8806                 edict = PRVM_EDICT_NUM(surfacelist[i]);
8807                 switch ((int)edict->fields.server->solid)
8808                 {
8809                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
8810                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
8811                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
8812                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
8813                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
8814                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
8815                 }
8816                 color[3] *= r_showbboxes.value;
8817                 color[3] = bound(0, color[3], 1);
8818                 GL_DepthTest(!r_showdisabledepthtest.integer);
8819                 GL_CullFace(r_refdef.view.cullface_front);
8820                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
8821         }
8822         SV_VM_End();
8823         prog = prog_save;
8824 }
8825
8826 static void R_DrawEntityBBoxes(void)
8827 {
8828         int i;
8829         prvm_edict_t *edict;
8830         vec3_t center;
8831         prvm_prog_t *prog_save = prog;
8832
8833         // this function draws bounding boxes of server entities
8834         if (!sv.active)
8835                 return;
8836
8837         prog = 0;
8838         SV_VM_Begin();
8839         for (i = 0;i < prog->num_edicts;i++)
8840         {
8841                 edict = PRVM_EDICT_NUM(i);
8842                 if (edict->priv.server->free)
8843                         continue;
8844                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
8845                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
8846                         continue;
8847                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
8848                         continue;
8849                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
8850                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
8851         }
8852         SV_VM_End();
8853         prog = prog_save;
8854 }
8855
8856 static const int nomodelelement3i[24] =
8857 {
8858         5, 2, 0,
8859         5, 1, 2,
8860         5, 0, 3,
8861         5, 3, 1,
8862         0, 2, 4,
8863         2, 1, 4,
8864         3, 0, 4,
8865         1, 3, 4
8866 };
8867
8868 static const unsigned short nomodelelement3s[24] =
8869 {
8870         5, 2, 0,
8871         5, 1, 2,
8872         5, 0, 3,
8873         5, 3, 1,
8874         0, 2, 4,
8875         2, 1, 4,
8876         3, 0, 4,
8877         1, 3, 4
8878 };
8879
8880 static const float nomodelvertex3f[6*3] =
8881 {
8882         -16,   0,   0,
8883          16,   0,   0,
8884           0, -16,   0,
8885           0,  16,   0,
8886           0,   0, -16,
8887           0,   0,  16
8888 };
8889
8890 static const float nomodelcolor4f[6*4] =
8891 {
8892         0.0f, 0.0f, 0.5f, 1.0f,
8893         0.0f, 0.0f, 0.5f, 1.0f,
8894         0.0f, 0.5f, 0.0f, 1.0f,
8895         0.0f, 0.5f, 0.0f, 1.0f,
8896         0.5f, 0.0f, 0.0f, 1.0f,
8897         0.5f, 0.0f, 0.0f, 1.0f
8898 };
8899
8900 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8901 {
8902         int i;
8903         float f1, f2, *c;
8904         float color4f[6*4];
8905
8906         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);
8907
8908         // this is only called once per entity so numsurfaces is always 1, and
8909         // surfacelist is always {0}, so this code does not handle batches
8910
8911         if (rsurface.ent_flags & RENDER_ADDITIVE)
8912         {
8913                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
8914                 GL_DepthMask(false);
8915         }
8916         else if (rsurface.colormod[3] < 1)
8917         {
8918                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8919                 GL_DepthMask(false);
8920         }
8921         else
8922         {
8923                 GL_BlendFunc(GL_ONE, GL_ZERO);
8924                 GL_DepthMask(true);
8925         }
8926         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8927         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8928         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8929         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8930         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8931         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8932         for (i = 0, c = color4f;i < 6;i++, c += 4)
8933         {
8934                 c[0] *= rsurface.colormod[0];
8935                 c[1] *= rsurface.colormod[1];
8936                 c[2] *= rsurface.colormod[2];
8937                 c[3] *= rsurface.colormod[3];
8938         }
8939         if (r_refdef.fogenabled)
8940         {
8941                 for (i = 0, c = color4f;i < 6;i++, c += 4)
8942                 {
8943                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
8944                         f2 = 1 - f1;
8945                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8946                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8947                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8948                 }
8949         }
8950         R_Mesh_ResetTextureState();
8951         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
8952         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
8953 }
8954
8955 void R_DrawNoModel(entity_render_t *ent)
8956 {
8957         vec3_t org;
8958         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8959         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8960                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8961         else
8962                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8963 }
8964
8965 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8966 {
8967         vec3_t right1, right2, diff, normal;
8968
8969         VectorSubtract (org2, org1, normal);
8970
8971         // calculate 'right' vector for start
8972         VectorSubtract (r_refdef.view.origin, org1, diff);
8973         CrossProduct (normal, diff, right1);
8974         VectorNormalize (right1);
8975
8976         // calculate 'right' vector for end
8977         VectorSubtract (r_refdef.view.origin, org2, diff);
8978         CrossProduct (normal, diff, right2);
8979         VectorNormalize (right2);
8980
8981         vert[ 0] = org1[0] + width * right1[0];
8982         vert[ 1] = org1[1] + width * right1[1];
8983         vert[ 2] = org1[2] + width * right1[2];
8984         vert[ 3] = org1[0] - width * right1[0];
8985         vert[ 4] = org1[1] - width * right1[1];
8986         vert[ 5] = org1[2] - width * right1[2];
8987         vert[ 6] = org2[0] - width * right2[0];
8988         vert[ 7] = org2[1] - width * right2[1];
8989         vert[ 8] = org2[2] - width * right2[2];
8990         vert[ 9] = org2[0] + width * right2[0];
8991         vert[10] = org2[1] + width * right2[1];
8992         vert[11] = org2[2] + width * right2[2];
8993 }
8994
8995 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)
8996 {
8997         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8998         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8999         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
9000         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
9001         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
9002         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
9003         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
9004         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
9005         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
9006         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
9007         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
9008         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
9009 }
9010
9011 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
9012 {
9013         int i;
9014         float *vertex3f;
9015         float v[3];
9016         VectorSet(v, x, y, z);
9017         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
9018                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
9019                         break;
9020         if (i == mesh->numvertices)
9021         {
9022                 if (mesh->numvertices < mesh->maxvertices)
9023                 {
9024                         VectorCopy(v, vertex3f);
9025                         mesh->numvertices++;
9026                 }
9027                 return mesh->numvertices;
9028         }
9029         else
9030                 return i;
9031 }
9032
9033 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
9034 {
9035         int i;
9036         int *e, element[3];
9037         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9038         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9039         e = mesh->element3i + mesh->numtriangles * 3;
9040         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
9041         {
9042                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
9043                 if (mesh->numtriangles < mesh->maxtriangles)
9044                 {
9045                         *e++ = element[0];
9046                         *e++ = element[1];
9047                         *e++ = element[2];
9048                         mesh->numtriangles++;
9049                 }
9050                 element[1] = element[2];
9051         }
9052 }
9053
9054 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
9055 {
9056         int i;
9057         int *e, element[3];
9058         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9059         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9060         e = mesh->element3i + mesh->numtriangles * 3;
9061         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
9062         {
9063                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
9064                 if (mesh->numtriangles < mesh->maxtriangles)
9065                 {
9066                         *e++ = element[0];
9067                         *e++ = element[1];
9068                         *e++ = element[2];
9069                         mesh->numtriangles++;
9070                 }
9071                 element[1] = element[2];
9072         }
9073 }
9074
9075 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
9076 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
9077 {
9078         int planenum, planenum2;
9079         int w;
9080         int tempnumpoints;
9081         mplane_t *plane, *plane2;
9082         double maxdist;
9083         double temppoints[2][256*3];
9084         // figure out how large a bounding box we need to properly compute this brush
9085         maxdist = 0;
9086         for (w = 0;w < numplanes;w++)
9087                 maxdist = max(maxdist, fabs(planes[w].dist));
9088         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
9089         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
9090         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
9091         {
9092                 w = 0;
9093                 tempnumpoints = 4;
9094                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
9095                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
9096                 {
9097                         if (planenum2 == planenum)
9098                                 continue;
9099                         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);
9100                         w = !w;
9101                 }
9102                 if (tempnumpoints < 3)
9103                         continue;
9104                 // generate elements forming a triangle fan for this polygon
9105                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
9106         }
9107 }
9108
9109 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)
9110 {
9111         texturelayer_t *layer;
9112         layer = t->currentlayers + t->currentnumlayers++;
9113         layer->type = type;
9114         layer->depthmask = depthmask;
9115         layer->blendfunc1 = blendfunc1;
9116         layer->blendfunc2 = blendfunc2;
9117         layer->texture = texture;
9118         layer->texmatrix = *matrix;
9119         layer->color[0] = r;
9120         layer->color[1] = g;
9121         layer->color[2] = b;
9122         layer->color[3] = a;
9123 }
9124
9125 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
9126 {
9127         double index, f;
9128         index = parms[2] + r_refdef.scene.time * parms[3];
9129         index -= floor(index);
9130         switch (func)
9131         {
9132         default:
9133         case Q3WAVEFUNC_NONE:
9134         case Q3WAVEFUNC_NOISE:
9135         case Q3WAVEFUNC_COUNT:
9136                 f = 0;
9137                 break;
9138         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
9139         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
9140         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
9141         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
9142         case Q3WAVEFUNC_TRIANGLE:
9143                 index *= 4;
9144                 f = index - floor(index);
9145                 if (index < 1)
9146                         f = f;
9147                 else if (index < 2)
9148                         f = 1 - f;
9149                 else if (index < 3)
9150                         f = -f;
9151                 else
9152                         f = -(1 - f);
9153                 break;
9154         }
9155         return (float)(parms[0] + parms[1] * f);
9156 }
9157
9158 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
9159 {
9160         int w, h, idx;
9161         float f;
9162         float tcmat[12];
9163         matrix4x4_t matrix, temp;
9164         switch(tcmod->tcmod)
9165         {
9166                 case Q3TCMOD_COUNT:
9167                 case Q3TCMOD_NONE:
9168                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9169                                 matrix = r_waterscrollmatrix;
9170                         else
9171                                 matrix = identitymatrix;
9172                         break;
9173                 case Q3TCMOD_ENTITYTRANSLATE:
9174                         // this is used in Q3 to allow the gamecode to control texcoord
9175                         // scrolling on the entity, which is not supported in darkplaces yet.
9176                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
9177                         break;
9178                 case Q3TCMOD_ROTATE:
9179                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
9180                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
9181                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
9182                         break;
9183                 case Q3TCMOD_SCALE:
9184                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
9185                         break;
9186                 case Q3TCMOD_SCROLL:
9187                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
9188                         break;
9189                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
9190                         w = (int) tcmod->parms[0];
9191                         h = (int) tcmod->parms[1];
9192                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
9193                         f = f - floor(f);
9194                         idx = (int) floor(f * w * h);
9195                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
9196                         break;
9197                 case Q3TCMOD_STRETCH:
9198                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
9199                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
9200                         break;
9201                 case Q3TCMOD_TRANSFORM:
9202                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
9203                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
9204                         VectorSet(tcmat +  6, 0                   , 0                , 1);
9205                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
9206                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
9207                         break;
9208                 case Q3TCMOD_TURBULENT:
9209                         // this is handled in the RSurf_PrepareVertices function
9210                         matrix = identitymatrix;
9211                         break;
9212         }
9213         temp = *texmatrix;
9214         Matrix4x4_Concat(texmatrix, &matrix, &temp);
9215 }
9216
9217 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
9218 {
9219         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
9220         char name[MAX_QPATH];
9221         skinframe_t *skinframe;
9222         unsigned char pixels[296*194];
9223         strlcpy(cache->name, skinname, sizeof(cache->name));
9224         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
9225         if (developer_loading.integer)
9226                 Con_Printf("loading %s\n", name);
9227         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
9228         if (!skinframe || !skinframe->base)
9229         {
9230                 unsigned char *f;
9231                 fs_offset_t filesize;
9232                 skinframe = NULL;
9233                 f = FS_LoadFile(name, tempmempool, true, &filesize);
9234                 if (f)
9235                 {
9236                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
9237                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
9238                         Mem_Free(f);
9239                 }
9240         }
9241         cache->skinframe = skinframe;
9242 }
9243
9244 texture_t *R_GetCurrentTexture(texture_t *t)
9245 {
9246         int i;
9247         const entity_render_t *ent = rsurface.entity;
9248         dp_model_t *model = ent->model;
9249         q3shaderinfo_layer_tcmod_t *tcmod;
9250
9251         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
9252                 return t->currentframe;
9253         t->update_lastrenderframe = r_textureframe;
9254         t->update_lastrenderentity = (void *)ent;
9255
9256         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
9257                 t->camera_entity = ent->entitynumber;
9258         else
9259                 t->camera_entity = 0;
9260
9261         // switch to an alternate material if this is a q1bsp animated material
9262         {
9263                 texture_t *texture = t;
9264                 int s = rsurface.ent_skinnum;
9265                 if ((unsigned int)s >= (unsigned int)model->numskins)
9266                         s = 0;
9267                 if (model->skinscenes)
9268                 {
9269                         if (model->skinscenes[s].framecount > 1)
9270                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
9271                         else
9272                                 s = model->skinscenes[s].firstframe;
9273                 }
9274                 if (s > 0)
9275                         t = t + s * model->num_surfaces;
9276                 if (t->animated)
9277                 {
9278                         // use an alternate animation if the entity's frame is not 0,
9279                         // and only if the texture has an alternate animation
9280                         if (rsurface.ent_alttextures && t->anim_total[1])
9281                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
9282                         else
9283                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
9284                 }
9285                 texture->currentframe = t;
9286         }
9287
9288         // update currentskinframe to be a qw skin or animation frame
9289         if (rsurface.ent_qwskin >= 0)
9290         {
9291                 i = rsurface.ent_qwskin;
9292                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
9293                 {
9294                         r_qwskincache_size = cl.maxclients;
9295                         if (r_qwskincache)
9296                                 Mem_Free(r_qwskincache);
9297                         r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
9298                 }
9299                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
9300                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
9301                 t->currentskinframe = r_qwskincache[i].skinframe;
9302                 if (t->currentskinframe == NULL)
9303                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9304         }
9305         else if (t->numskinframes >= 2)
9306                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9307         if (t->backgroundnumskinframes >= 2)
9308                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
9309
9310         t->currentmaterialflags = t->basematerialflags;
9311         t->currentalpha = rsurface.colormod[3];
9312         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
9313                 t->currentalpha *= r_wateralpha.value;
9314         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
9315                 t->currentalpha *= t->r_water_wateralpha;
9316         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
9317                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
9318         if (!(rsurface.ent_flags & RENDER_LIGHT))
9319                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
9320         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
9321         {
9322                 // pick a model lighting mode
9323                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
9324                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
9325                 else
9326                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
9327         }
9328         if (rsurface.ent_flags & RENDER_ADDITIVE)
9329                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9330         else if (t->currentalpha < 1)
9331                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9332         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
9333                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
9334         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
9335                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
9336         if (t->backgroundnumskinframes)
9337                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
9338         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
9339         {
9340                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
9341                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
9342         }
9343         else
9344                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
9345         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
9346                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
9347
9348         // there is no tcmod
9349         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9350         {
9351                 t->currenttexmatrix = r_waterscrollmatrix;
9352                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
9353         }
9354         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
9355         {
9356                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
9357                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
9358         }
9359
9360         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9361                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
9362         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9363                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
9364
9365         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
9366         if (t->currentskinframe->qpixels)
9367                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
9368         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
9369         if (!t->basetexture)
9370                 t->basetexture = r_texture_notexture;
9371         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
9372         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
9373         t->nmaptexture = t->currentskinframe->nmap;
9374         if (!t->nmaptexture)
9375                 t->nmaptexture = r_texture_blanknormalmap;
9376         t->glosstexture = r_texture_black;
9377         t->glowtexture = t->currentskinframe->glow;
9378         t->fogtexture = t->currentskinframe->fog;
9379         t->reflectmasktexture = t->currentskinframe->reflect;
9380         if (t->backgroundnumskinframes)
9381         {
9382                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
9383                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
9384                 t->backgroundglosstexture = r_texture_black;
9385                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
9386                 if (!t->backgroundnmaptexture)
9387                         t->backgroundnmaptexture = r_texture_blanknormalmap;
9388         }
9389         else
9390         {
9391                 t->backgroundbasetexture = r_texture_white;
9392                 t->backgroundnmaptexture = r_texture_blanknormalmap;
9393                 t->backgroundglosstexture = r_texture_black;
9394                 t->backgroundglowtexture = NULL;
9395         }
9396         t->specularpower = r_shadow_glossexponent.value;
9397         // TODO: store reference values for these in the texture?
9398         t->specularscale = 0;
9399         if (r_shadow_gloss.integer > 0)
9400         {
9401                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
9402                 {
9403                         if (r_shadow_glossintensity.value > 0)
9404                         {
9405                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
9406                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
9407                                 t->specularscale = r_shadow_glossintensity.value;
9408                         }
9409                 }
9410                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
9411                 {
9412                         t->glosstexture = r_texture_white;
9413                         t->backgroundglosstexture = r_texture_white;
9414                         t->specularscale = r_shadow_gloss2intensity.value;
9415                         t->specularpower = r_shadow_gloss2exponent.value;
9416                 }
9417         }
9418         t->specularscale *= t->specularscalemod;
9419         t->specularpower *= t->specularpowermod;
9420
9421         // lightmaps mode looks bad with dlights using actual texturing, so turn
9422         // off the colormap and glossmap, but leave the normalmap on as it still
9423         // accurately represents the shading involved
9424         if (gl_lightmaps.integer)
9425         {
9426                 t->basetexture = r_texture_grey128;
9427                 t->pantstexture = r_texture_black;
9428                 t->shirttexture = r_texture_black;
9429                 t->nmaptexture = r_texture_blanknormalmap;
9430                 t->glosstexture = r_texture_black;
9431                 t->glowtexture = NULL;
9432                 t->fogtexture = NULL;
9433                 t->reflectmasktexture = NULL;
9434                 t->backgroundbasetexture = NULL;
9435                 t->backgroundnmaptexture = r_texture_blanknormalmap;
9436                 t->backgroundglosstexture = r_texture_black;
9437                 t->backgroundglowtexture = NULL;
9438                 t->specularscale = 0;
9439                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
9440         }
9441
9442         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
9443         VectorClear(t->dlightcolor);
9444         t->currentnumlayers = 0;
9445         if (t->currentmaterialflags & MATERIALFLAG_WALL)
9446         {
9447                 int blendfunc1, blendfunc2;
9448                 qboolean depthmask;
9449                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
9450                 {
9451                         blendfunc1 = GL_SRC_ALPHA;
9452                         blendfunc2 = GL_ONE;
9453                 }
9454                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
9455                 {
9456                         blendfunc1 = GL_SRC_ALPHA;
9457                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
9458                 }
9459                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9460                 {
9461                         blendfunc1 = t->customblendfunc[0];
9462                         blendfunc2 = t->customblendfunc[1];
9463                 }
9464                 else
9465                 {
9466                         blendfunc1 = GL_ONE;
9467                         blendfunc2 = GL_ZERO;
9468                 }
9469                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
9470                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9471                 {
9472                         // fullbright is not affected by r_refdef.lightmapintensity
9473                         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]);
9474                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9475                                 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]);
9476                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9477                                 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]);
9478                 }
9479                 else
9480                 {
9481                         vec3_t ambientcolor;
9482                         float colorscale;
9483                         // set the color tint used for lights affecting this surface
9484                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
9485                         colorscale = 2;
9486                         // q3bsp has no lightmap updates, so the lightstylevalue that
9487                         // would normally be baked into the lightmap must be
9488                         // applied to the color
9489                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
9490                         if (model->type == mod_brushq3)
9491                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
9492                         colorscale *= r_refdef.lightmapintensity;
9493                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
9494                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
9495                         // basic lit geometry
9496                         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]);
9497                         // add pants/shirt if needed
9498                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9499                                 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]);
9500                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9501                                 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]);
9502                         // now add ambient passes if needed
9503                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
9504                         {
9505                                 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]);
9506                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9507                                         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]);
9508                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9509                                         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]);
9510                         }
9511                 }
9512                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
9513                         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]);
9514                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
9515                 {
9516                         // if this is opaque use alpha blend which will darken the earlier
9517                         // passes cheaply.
9518                         //
9519                         // if this is an alpha blended material, all the earlier passes
9520                         // were darkened by fog already, so we only need to add the fog
9521                         // color ontop through the fog mask texture
9522                         //
9523                         // if this is an additive blended material, all the earlier passes
9524                         // were darkened by fog already, and we should not add fog color
9525                         // (because the background was not darkened, there is no fog color
9526                         // that was lost behind it).
9527                         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]);
9528                 }
9529         }
9530
9531         return t->currentframe;
9532 }
9533
9534 rsurfacestate_t rsurface;
9535
9536 void R_Mesh_ResizeArrays(int newvertices)
9537 {
9538         unsigned char *base;
9539         size_t size;
9540         if (rsurface.array_size >= newvertices)
9541                 return;
9542         if (rsurface.array_base)
9543                 Mem_Free(rsurface.array_base);
9544         rsurface.array_size = (newvertices + 1023) & ~1023;
9545         size = 0;
9546         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
9547         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
9548         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
9549         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
9550         size += rsurface.array_size * sizeof(float[3]);
9551         size += rsurface.array_size * sizeof(float[3]);
9552         size += rsurface.array_size * sizeof(float[3]);
9553         size += rsurface.array_size * sizeof(float[3]);
9554         size += rsurface.array_size * sizeof(float[3]);
9555         size += rsurface.array_size * sizeof(float[3]);
9556         size += rsurface.array_size * sizeof(float[3]);
9557         size += rsurface.array_size * sizeof(float[3]);
9558         size += rsurface.array_size * sizeof(float[4]);
9559         size += rsurface.array_size * sizeof(float[2]);
9560         size += rsurface.array_size * sizeof(float[2]);
9561         size += rsurface.array_size * sizeof(float[4]);
9562         size += rsurface.array_size * sizeof(int[3]);
9563         size += rsurface.array_size * sizeof(unsigned short[3]);
9564         rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
9565         rsurface.array_modelvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
9566         rsurface.array_batchvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
9567         rsurface.array_modelvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
9568         rsurface.array_batchvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
9569         rsurface.array_modelvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
9570         rsurface.array_modelsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
9571         rsurface.array_modeltvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
9572         rsurface.array_modelnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
9573         rsurface.array_batchvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
9574         rsurface.array_batchsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
9575         rsurface.array_batchtvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
9576         rsurface.array_batchnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
9577         rsurface.array_batchlightmapcolor4f    = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
9578         rsurface.array_batchtexcoordtexture2f  = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
9579         rsurface.array_batchtexcoordlightmap2f = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
9580         rsurface.array_passcolor4f             = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
9581         rsurface.array_batchelement3i          = (int                *)base;base += rsurface.array_size * sizeof(int[3]);
9582         rsurface.array_batchelement3s          = (unsigned short     *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
9583 }
9584
9585 void RSurf_ActiveWorldEntity(void)
9586 {
9587         dp_model_t *model = r_refdef.scene.worldmodel;
9588         //if (rsurface.entity == r_refdef.scene.worldentity)
9589         //      return;
9590         rsurface.entity = r_refdef.scene.worldentity;
9591         rsurface.skeleton = NULL;
9592         rsurface.ent_skinnum = 0;
9593         rsurface.ent_qwskin = -1;
9594         rsurface.ent_shadertime = 0;
9595         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
9596         if (rsurface.array_size < model->surfmesh.num_vertices)
9597                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9598         rsurface.matrix = identitymatrix;
9599         rsurface.inversematrix = identitymatrix;
9600         rsurface.matrixscale = 1;
9601         rsurface.inversematrixscale = 1;
9602         R_EntityMatrix(&identitymatrix);
9603         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
9604         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
9605         rsurface.fograngerecip = r_refdef.fograngerecip;
9606         rsurface.fogheightfade = r_refdef.fogheightfade;
9607         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
9608         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9609         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9610         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9611         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9612         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9613         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9614         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
9615         rsurface.colormod[3] = 1;
9616         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);
9617         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9618         rsurface.frameblend[0].lerp = 1;
9619         rsurface.ent_alttextures = false;
9620         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9621         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9622         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
9623         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9624         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9625         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9626         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9627         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9628         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9629         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9630         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9631         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
9632         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9633         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9634         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
9635         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9636         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9637         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
9638         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9639         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9640         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
9641         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9642         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9643         rsurface.modelelement3i = model->surfmesh.data_element3i;
9644         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
9645         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
9646         rsurface.modelelement3s = model->surfmesh.data_element3s;
9647         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
9648         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
9649         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9650         rsurface.modelnumvertices = model->surfmesh.num_vertices;
9651         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
9652         rsurface.modelsurfaces = model->data_surfaces;
9653         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
9654         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
9655         rsurface.modelvertexposition = model->surfmesh.vertexposition;
9656         rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
9657         rsurface.modelgeneratedvertex = false;
9658         rsurface.batchgeneratedvertex = false;
9659         rsurface.batchfirstvertex = 0;
9660         rsurface.batchnumvertices = 0;
9661         rsurface.batchfirsttriangle = 0;
9662         rsurface.batchnumtriangles = 0;
9663         rsurface.batchvertex3f  = NULL;
9664         rsurface.batchvertex3f_vertexbuffer = NULL;
9665         rsurface.batchvertex3f_bufferoffset = 0;
9666         rsurface.batchsvector3f = NULL;
9667         rsurface.batchsvector3f_vertexbuffer = NULL;
9668         rsurface.batchsvector3f_bufferoffset = 0;
9669         rsurface.batchtvector3f = NULL;
9670         rsurface.batchtvector3f_vertexbuffer = NULL;
9671         rsurface.batchtvector3f_bufferoffset = 0;
9672         rsurface.batchnormal3f  = NULL;
9673         rsurface.batchnormal3f_vertexbuffer = NULL;
9674         rsurface.batchnormal3f_bufferoffset = 0;
9675         rsurface.batchlightmapcolor4f = NULL;
9676         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9677         rsurface.batchlightmapcolor4f_bufferoffset = 0;
9678         rsurface.batchtexcoordtexture2f = NULL;
9679         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9680         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9681         rsurface.batchtexcoordlightmap2f = NULL;
9682         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9683         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9684         rsurface.batchvertexmesh = NULL;
9685         rsurface.batchvertexmeshbuffer = NULL;
9686         rsurface.batchvertexposition = NULL;
9687         rsurface.batchvertexpositionbuffer = NULL;
9688         rsurface.batchelement3i = NULL;
9689         rsurface.batchelement3i_indexbuffer = NULL;
9690         rsurface.batchelement3i_bufferoffset = 0;
9691         rsurface.batchelement3s = NULL;
9692         rsurface.batchelement3s_indexbuffer = NULL;
9693         rsurface.batchelement3s_bufferoffset = 0;
9694         rsurface.passcolor4f = NULL;
9695         rsurface.passcolor4f_vertexbuffer = NULL;
9696         rsurface.passcolor4f_bufferoffset = 0;
9697 }
9698
9699 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
9700 {
9701         dp_model_t *model = ent->model;
9702         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
9703         //      return;
9704         rsurface.entity = (entity_render_t *)ent;
9705         rsurface.skeleton = ent->skeleton;
9706         rsurface.ent_skinnum = ent->skinnum;
9707         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;
9708         rsurface.ent_shadertime = ent->shadertime;
9709         rsurface.ent_flags = ent->flags;
9710         if (rsurface.array_size < model->surfmesh.num_vertices)
9711                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9712         rsurface.matrix = ent->matrix;
9713         rsurface.inversematrix = ent->inversematrix;
9714         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9715         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9716         R_EntityMatrix(&rsurface.matrix);
9717         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9718         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9719         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9720         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9721         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9722         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9723         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
9724         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
9725         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
9726         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
9727         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
9728         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
9729         rsurface.colormod[3] = ent->alpha;
9730         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
9731         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
9732         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
9733         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9734         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9735         if (ent->model->brush.submodel && !prepass)
9736         {
9737                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
9738                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
9739         }
9740         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
9741         {
9742                 if (ent->animcache_vertex3f && !r_framedata_failed)
9743                 {
9744                         rsurface.modelvertex3f = ent->animcache_vertex3f;
9745                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
9746                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
9747                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
9748                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
9749                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
9750                         rsurface.modelvertexposition = ent->animcache_vertexposition;
9751                         rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
9752                 }
9753                 else if (wanttangents)
9754                 {
9755                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9756                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9757                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9758                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9759                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
9760                         rsurface.modelvertexmesh = NULL;
9761                         rsurface.modelvertexmeshbuffer = NULL;
9762                         rsurface.modelvertexposition = NULL;
9763                         rsurface.modelvertexpositionbuffer = NULL;
9764                 }
9765                 else if (wantnormals)
9766                 {
9767                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9768                         rsurface.modelsvector3f = NULL;
9769                         rsurface.modeltvector3f = NULL;
9770                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9771                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
9772                         rsurface.modelvertexmesh = NULL;
9773                         rsurface.modelvertexmeshbuffer = NULL;
9774                         rsurface.modelvertexposition = NULL;
9775                         rsurface.modelvertexpositionbuffer = NULL;
9776                 }
9777                 else
9778                 {
9779                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9780                         rsurface.modelsvector3f = NULL;
9781                         rsurface.modeltvector3f = NULL;
9782                         rsurface.modelnormal3f = NULL;
9783                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
9784                         rsurface.modelvertexmesh = NULL;
9785                         rsurface.modelvertexmeshbuffer = NULL;
9786                         rsurface.modelvertexposition = NULL;
9787                         rsurface.modelvertexpositionbuffer = NULL;
9788                 }
9789                 rsurface.modelvertex3f_vertexbuffer = 0;
9790                 rsurface.modelvertex3f_bufferoffset = 0;
9791                 rsurface.modelsvector3f_vertexbuffer = 0;
9792                 rsurface.modelsvector3f_bufferoffset = 0;
9793                 rsurface.modeltvector3f_vertexbuffer = 0;
9794                 rsurface.modeltvector3f_bufferoffset = 0;
9795                 rsurface.modelnormal3f_vertexbuffer = 0;
9796                 rsurface.modelnormal3f_bufferoffset = 0;
9797                 rsurface.modelgeneratedvertex = true;
9798         }
9799         else
9800         {
9801                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
9802                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9803                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9804                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9805                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9806                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9807                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9808                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9809                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9810                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
9811                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9812                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9813                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
9814                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
9815                 rsurface.modelvertexposition = model->surfmesh.vertexposition;
9816                 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
9817                 rsurface.modelgeneratedvertex = false;
9818         }
9819         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
9820         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9821         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9822         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
9823         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9824         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9825         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
9826         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9827         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9828         rsurface.modelelement3i = model->surfmesh.data_element3i;
9829         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
9830         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
9831         rsurface.modelelement3s = model->surfmesh.data_element3s;
9832         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
9833         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
9834         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9835         rsurface.modelnumvertices = model->surfmesh.num_vertices;
9836         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
9837         rsurface.modelsurfaces = model->data_surfaces;
9838         rsurface.batchgeneratedvertex = false;
9839         rsurface.batchfirstvertex = 0;
9840         rsurface.batchnumvertices = 0;
9841         rsurface.batchfirsttriangle = 0;
9842         rsurface.batchnumtriangles = 0;
9843         rsurface.batchvertex3f  = NULL;
9844         rsurface.batchvertex3f_vertexbuffer = NULL;
9845         rsurface.batchvertex3f_bufferoffset = 0;
9846         rsurface.batchsvector3f = NULL;
9847         rsurface.batchsvector3f_vertexbuffer = NULL;
9848         rsurface.batchsvector3f_bufferoffset = 0;
9849         rsurface.batchtvector3f = NULL;
9850         rsurface.batchtvector3f_vertexbuffer = NULL;
9851         rsurface.batchtvector3f_bufferoffset = 0;
9852         rsurface.batchnormal3f  = NULL;
9853         rsurface.batchnormal3f_vertexbuffer = NULL;
9854         rsurface.batchnormal3f_bufferoffset = 0;
9855         rsurface.batchlightmapcolor4f = NULL;
9856         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9857         rsurface.batchlightmapcolor4f_bufferoffset = 0;
9858         rsurface.batchtexcoordtexture2f = NULL;
9859         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9860         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9861         rsurface.batchtexcoordlightmap2f = NULL;
9862         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9863         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9864         rsurface.batchvertexmesh = NULL;
9865         rsurface.batchvertexmeshbuffer = NULL;
9866         rsurface.batchvertexposition = NULL;
9867         rsurface.batchvertexpositionbuffer = NULL;
9868         rsurface.batchelement3i = NULL;
9869         rsurface.batchelement3i_indexbuffer = NULL;
9870         rsurface.batchelement3i_bufferoffset = 0;
9871         rsurface.batchelement3s = NULL;
9872         rsurface.batchelement3s_indexbuffer = NULL;
9873         rsurface.batchelement3s_bufferoffset = 0;
9874         rsurface.passcolor4f = NULL;
9875         rsurface.passcolor4f_vertexbuffer = NULL;
9876         rsurface.passcolor4f_bufferoffset = 0;
9877 }
9878
9879 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)
9880 {
9881         int i;
9882
9883         rsurface.entity = r_refdef.scene.worldentity;
9884         rsurface.skeleton = NULL;
9885         rsurface.ent_skinnum = 0;
9886         rsurface.ent_qwskin = -1;
9887         rsurface.ent_shadertime = shadertime;
9888         rsurface.ent_flags = entflags;
9889         rsurface.modelnumvertices = numvertices;
9890         rsurface.modelnumtriangles = numtriangles;
9891         if (rsurface.array_size < rsurface.modelnumvertices)
9892                 R_Mesh_ResizeArrays(rsurface.modelnumvertices);
9893         rsurface.matrix = *matrix;
9894         rsurface.inversematrix = *inversematrix;
9895         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9896         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9897         R_EntityMatrix(&rsurface.matrix);
9898         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9899         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9900         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9901         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9902         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9903         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9904         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9905         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9906         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9907         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9908         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9909         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
9910         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);
9911         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9912         rsurface.frameblend[0].lerp = 1;
9913         rsurface.ent_alttextures = false;
9914         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9915         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9916         if (wanttangents)
9917         {
9918                 rsurface.modelvertex3f = vertex3f;
9919                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
9920                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
9921                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9922         }
9923         else if (wantnormals)
9924         {
9925                 rsurface.modelvertex3f = vertex3f;
9926                 rsurface.modelsvector3f = NULL;
9927                 rsurface.modeltvector3f = NULL;
9928                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9929         }
9930         else
9931         {
9932                 rsurface.modelvertex3f = vertex3f;
9933                 rsurface.modelsvector3f = NULL;
9934                 rsurface.modeltvector3f = NULL;
9935                 rsurface.modelnormal3f = NULL;
9936         }
9937         rsurface.modelvertexmesh = NULL;
9938         rsurface.modelvertexmeshbuffer = NULL;
9939         rsurface.modelvertexposition = NULL;
9940         rsurface.modelvertexpositionbuffer = NULL;
9941         rsurface.modelvertex3f_vertexbuffer = 0;
9942         rsurface.modelvertex3f_bufferoffset = 0;
9943         rsurface.modelsvector3f_vertexbuffer = 0;
9944         rsurface.modelsvector3f_bufferoffset = 0;
9945         rsurface.modeltvector3f_vertexbuffer = 0;
9946         rsurface.modeltvector3f_bufferoffset = 0;
9947         rsurface.modelnormal3f_vertexbuffer = 0;
9948         rsurface.modelnormal3f_bufferoffset = 0;
9949         rsurface.modelgeneratedvertex = true;
9950         rsurface.modellightmapcolor4f  = color4f;
9951         rsurface.modellightmapcolor4f_vertexbuffer = 0;
9952         rsurface.modellightmapcolor4f_bufferoffset = 0;
9953         rsurface.modeltexcoordtexture2f  = texcoord2f;
9954         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
9955         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9956         rsurface.modeltexcoordlightmap2f  = NULL;
9957         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
9958         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9959         rsurface.modelelement3i = element3i;
9960         rsurface.modelelement3i_indexbuffer = NULL;
9961         rsurface.modelelement3i_bufferoffset = 0;
9962         rsurface.modelelement3s = element3s;
9963         rsurface.modelelement3s_indexbuffer = NULL;
9964         rsurface.modelelement3s_bufferoffset = 0;
9965         rsurface.modellightmapoffsets = NULL;
9966         rsurface.modelsurfaces = NULL;
9967         rsurface.batchgeneratedvertex = false;
9968         rsurface.batchfirstvertex = 0;
9969         rsurface.batchnumvertices = 0;
9970         rsurface.batchfirsttriangle = 0;
9971         rsurface.batchnumtriangles = 0;
9972         rsurface.batchvertex3f  = NULL;
9973         rsurface.batchvertex3f_vertexbuffer = NULL;
9974         rsurface.batchvertex3f_bufferoffset = 0;
9975         rsurface.batchsvector3f = NULL;
9976         rsurface.batchsvector3f_vertexbuffer = NULL;
9977         rsurface.batchsvector3f_bufferoffset = 0;
9978         rsurface.batchtvector3f = NULL;
9979         rsurface.batchtvector3f_vertexbuffer = NULL;
9980         rsurface.batchtvector3f_bufferoffset = 0;
9981         rsurface.batchnormal3f  = NULL;
9982         rsurface.batchnormal3f_vertexbuffer = NULL;
9983         rsurface.batchnormal3f_bufferoffset = 0;
9984         rsurface.batchlightmapcolor4f = NULL;
9985         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9986         rsurface.batchlightmapcolor4f_bufferoffset = 0;
9987         rsurface.batchtexcoordtexture2f = NULL;
9988         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9989         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9990         rsurface.batchtexcoordlightmap2f = NULL;
9991         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9992         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9993         rsurface.batchvertexmesh = NULL;
9994         rsurface.batchvertexmeshbuffer = NULL;
9995         rsurface.batchvertexposition = NULL;
9996         rsurface.batchvertexpositionbuffer = NULL;
9997         rsurface.batchelement3i = NULL;
9998         rsurface.batchelement3i_indexbuffer = NULL;
9999         rsurface.batchelement3i_bufferoffset = 0;
10000         rsurface.batchelement3s = NULL;
10001         rsurface.batchelement3s_indexbuffer = NULL;
10002         rsurface.batchelement3s_bufferoffset = 0;
10003         rsurface.passcolor4f = NULL;
10004         rsurface.passcolor4f_vertexbuffer = NULL;
10005         rsurface.passcolor4f_bufferoffset = 0;
10006
10007         if (rsurface.modelnumvertices && rsurface.modelelement3i)
10008         {
10009                 if ((wantnormals || wanttangents) && !normal3f)
10010                 {
10011                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
10012                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10013                 }
10014                 if (wanttangents && !svector3f)
10015                 {
10016                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
10017                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10018                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10019                 }
10020         }
10021
10022         // now convert arrays into vertexmesh structs
10023         for (i = 0;i < numvertices;i++)
10024         {
10025                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexposition[i].vertex3f);
10026                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexmesh[i].vertex3f);
10027                 if (rsurface.modelsvector3f)
10028                         VectorCopy(rsurface.modelsvector3f + 3*i, rsurface.array_modelvertexmesh[i].svector3f);
10029                 if (rsurface.modeltvector3f)
10030                         VectorCopy(rsurface.modeltvector3f + 3*i, rsurface.array_modelvertexmesh[i].tvector3f);
10031                 if (rsurface.modelnormal3f)
10032                         VectorCopy(rsurface.modelnormal3f + 3*i, rsurface.array_modelvertexmesh[i].normal3f);
10033                 if (rsurface.modellightmapcolor4f)
10034                         Vector4Scale(rsurface.modellightmapcolor4f + 4*i, 255.0f, rsurface.array_modelvertexmesh[i].color4ub);
10035                 if (rsurface.modeltexcoordtexture2f)
10036                         Vector2Copy(rsurface.modeltexcoordtexture2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordtexture2f);
10037                 if (rsurface.modeltexcoordlightmap2f)
10038                         Vector2Copy(rsurface.modeltexcoordlightmap2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordlightmap2f);
10039         }
10040 }
10041
10042 float RSurf_FogPoint(const float *v)
10043 {
10044         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10045         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
10046         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
10047         float FogHeightFade = r_refdef.fogheightfade;
10048         float fogfrac;
10049         unsigned int fogmasktableindex;
10050         if (r_refdef.fogplaneviewabove)
10051                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10052         else
10053                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10054         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
10055         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10056 }
10057
10058 float RSurf_FogVertex(const float *v)
10059 {
10060         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10061         float FogPlaneViewDist = rsurface.fogplaneviewdist;
10062         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
10063         float FogHeightFade = rsurface.fogheightfade;
10064         float fogfrac;
10065         unsigned int fogmasktableindex;
10066         if (r_refdef.fogplaneviewabove)
10067                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10068         else
10069                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10070         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
10071         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10072 }
10073
10074 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
10075 {
10076         int i;
10077         for (i = 0;i < numelements;i++)
10078                 outelement3i[i] = inelement3i[i] + adjust;
10079 }
10080
10081 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
10082 extern cvar_t gl_vbo;
10083 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
10084 {
10085         int deformindex;
10086         int firsttriangle;
10087         int numtriangles;
10088         int firstvertex;
10089         int endvertex;
10090         int numvertices;
10091         int surfacefirsttriangle;
10092         int surfacenumtriangles;
10093         int surfacefirstvertex;
10094         int surfaceendvertex;
10095         int surfacenumvertices;
10096         int surfaceadjustvertex;
10097         int needsupdate;
10098         int i, j;
10099         qboolean gaps;
10100         qboolean dynamicvertex;
10101         float amplitude;
10102         float animpos;
10103         float scale;
10104         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
10105         float waveparms[4];
10106         q3shaderinfo_deform_t *deform;
10107         const msurface_t *surface, *firstsurface;
10108         r_vertexposition_t *vertexposition;
10109         r_vertexmesh_t *vertexmesh;
10110         if (!texturenumsurfaces)
10111                 return;
10112         // find vertex range of this surface batch
10113         gaps = false;
10114         firstsurface = texturesurfacelist[0];
10115         firsttriangle = firstsurface->num_firsttriangle;
10116         numtriangles = 0;
10117         firstvertex = endvertex = firstsurface->num_firstvertex;
10118         for (i = 0;i < texturenumsurfaces;i++)
10119         {
10120                 surface = texturesurfacelist[i];
10121                 if (surface != firstsurface + i)
10122                         gaps = true;
10123                 surfacefirstvertex = surface->num_firstvertex;
10124                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
10125                 surfacenumtriangles = surface->num_triangles;
10126                 if (firstvertex > surfacefirstvertex)
10127                         firstvertex = surfacefirstvertex;
10128                 if (endvertex < surfaceendvertex)
10129                         endvertex = surfaceendvertex;
10130                 numtriangles += surfacenumtriangles;
10131         }
10132         if (!numtriangles)
10133                 return;
10134
10135         // we now know the vertex range used, and if there are any gaps in it
10136         rsurface.batchfirstvertex = firstvertex;
10137         rsurface.batchnumvertices = endvertex - firstvertex;
10138         rsurface.batchfirsttriangle = firsttriangle;
10139         rsurface.batchnumtriangles = numtriangles;
10140
10141         // this variable holds flags for which properties have been updated that
10142         // may require regenerating vertexmesh or vertexposition arrays...
10143         needsupdate = 0;
10144
10145         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
10146                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
10147         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
10148         {
10149                 switch (deform->deform)
10150                 {
10151                 default:
10152                 case Q3DEFORM_PROJECTIONSHADOW:
10153                 case Q3DEFORM_TEXT0:
10154                 case Q3DEFORM_TEXT1:
10155                 case Q3DEFORM_TEXT2:
10156                 case Q3DEFORM_TEXT3:
10157                 case Q3DEFORM_TEXT4:
10158                 case Q3DEFORM_TEXT5:
10159                 case Q3DEFORM_TEXT6:
10160                 case Q3DEFORM_TEXT7:
10161                 case Q3DEFORM_NONE:
10162                         break;
10163                 case Q3DEFORM_AUTOSPRITE:
10164                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10165                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10166                         break;
10167                 case Q3DEFORM_AUTOSPRITE2:
10168                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10169                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10170                         break;
10171                 case Q3DEFORM_NORMAL:
10172                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10173                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10174                         break;
10175                 case Q3DEFORM_WAVE:
10176                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10177                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10178                         break;
10179                 case Q3DEFORM_BULGE:
10180                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10181                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10182                         break;
10183                 case Q3DEFORM_MOVE:
10184                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
10185                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
10186                         break;
10187                 }
10188         }
10189         switch(rsurface.texture->tcgen.tcgen)
10190         {
10191         default:
10192         case Q3TCGEN_TEXTURE:
10193                 break;
10194         case Q3TCGEN_LIGHTMAP:
10195                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
10196                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
10197                 break;
10198         case Q3TCGEN_VECTOR:
10199                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
10200                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
10201                 break;
10202         case Q3TCGEN_ENVIRONMENT:
10203                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
10204                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
10205                 break;
10206         }
10207         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10208         {
10209                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
10210                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
10211         }
10212
10213         // check if any dynamic vertex processing must occur
10214         dynamicvertex = false;
10215
10216         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
10217         {
10218                 dynamicvertex = true;
10219                 batchneed |= BATCHNEED_NOGAPS;
10220                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
10221         }
10222
10223         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
10224         {
10225                 dynamicvertex = true;
10226                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
10227                 needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
10228         }
10229
10230         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
10231         {
10232                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
10233                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
10234                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
10235                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
10236                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
10237                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
10238                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
10239         }
10240
10241         // when the model data has no vertex buffer (dynamic mesh), we need to
10242         // eliminate gaps
10243         if (!rsurface.modelvertexmeshbuffer || (!gl_vbo.integer && !vid.forcevbo))
10244                 batchneed |= BATCHNEED_NOGAPS;
10245
10246         // if needsupdate, we have to do a dynamic vertex batch for sure
10247         if (needsupdate & batchneed)
10248                 dynamicvertex = true;
10249
10250         // see if we need to build vertexmesh from arrays
10251         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
10252                 dynamicvertex = true;
10253
10254         // see if we need to build vertexposition from arrays
10255         if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
10256                 dynamicvertex = true;
10257
10258         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
10259         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
10260                 dynamicvertex = true;
10261
10262         // if there is a chance of animated vertex colors, it's a dynamic batch
10263         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
10264                 dynamicvertex = true;
10265
10266         rsurface.batchvertex3f = rsurface.modelvertex3f;
10267         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
10268         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
10269         rsurface.batchsvector3f = rsurface.modelsvector3f;
10270         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
10271         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
10272         rsurface.batchtvector3f = rsurface.modeltvector3f;
10273         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
10274         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
10275         rsurface.batchnormal3f = rsurface.modelnormal3f;
10276         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
10277         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
10278         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
10279         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
10280         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
10281         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
10282         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
10283         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
10284         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
10285         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
10286         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
10287         rsurface.batchvertexposition = rsurface.modelvertexposition;
10288         rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
10289         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
10290         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
10291         rsurface.batchelement3i = rsurface.modelelement3i;
10292         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
10293         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
10294         rsurface.batchelement3s = rsurface.modelelement3s;
10295         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
10296         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
10297
10298         // if any dynamic vertex processing has to occur in software, we copy the
10299         // entire surface list together before processing to rebase the vertices
10300         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
10301         //
10302         // if any gaps exist and we do not have a static vertex buffer, we have to
10303         // copy the surface list together to avoid wasting upload bandwidth on the
10304         // vertices in the gaps.
10305         //
10306         // if gaps exist and we have a static vertex buffer, we still have to
10307         // combine the index buffer ranges into one dynamic index buffer.
10308         //
10309         // in all cases we end up with data that can be drawn in one call.
10310
10311         if (!dynamicvertex)
10312         {
10313                 // static vertex data, just set pointers...
10314                 rsurface.batchgeneratedvertex = false;
10315                 // if there are gaps, we want to build a combined index buffer,
10316                 // otherwise use the original static buffer with an appropriate offset
10317                 if (gaps)
10318                 {
10319                         firsttriangle = 0;
10320                         numtriangles = 0;
10321                         for (i = 0;i < texturenumsurfaces;i++)
10322                         {
10323                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
10324                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
10325                                 memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
10326                                 numtriangles += surfacenumtriangles;
10327                         }
10328                         rsurface.batchelement3i = rsurface.array_batchelement3i;
10329                         rsurface.batchelement3i_indexbuffer = NULL;
10330                         rsurface.batchelement3i_bufferoffset = 0;
10331                         rsurface.batchelement3s = NULL;
10332                         rsurface.batchelement3s_indexbuffer = NULL;
10333                         rsurface.batchelement3s_bufferoffset = 0;
10334                         if (endvertex <= 65536)
10335                         {
10336                                 rsurface.batchelement3s = rsurface.array_batchelement3s;
10337                                 for (i = 0;i < numtriangles*3;i++)
10338                                         rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
10339                         }
10340                         rsurface.batchfirsttriangle = firsttriangle;
10341                         rsurface.batchnumtriangles = numtriangles;
10342                 }
10343                 return;
10344         }
10345
10346         // something needs software processing, do it for real...
10347         // we only directly handle interleaved array data in this case...
10348         rsurface.batchgeneratedvertex = true;
10349
10350         // now copy the vertex data into a combined array and make an index array
10351         // (this is what Quake3 does all the time)
10352         //if (gaps || rsurface.batchfirstvertex)
10353         {
10354                 rsurface.batchvertexposition = NULL;
10355                 rsurface.batchvertexpositionbuffer = NULL;
10356                 rsurface.batchvertexmesh = NULL;
10357                 rsurface.batchvertexmeshbuffer = NULL;
10358                 rsurface.batchvertex3f = NULL;
10359                 rsurface.batchvertex3f_vertexbuffer = NULL;
10360                 rsurface.batchvertex3f_bufferoffset = 0;
10361                 rsurface.batchsvector3f = NULL;
10362                 rsurface.batchsvector3f_vertexbuffer = NULL;
10363                 rsurface.batchsvector3f_bufferoffset = 0;
10364                 rsurface.batchtvector3f = NULL;
10365                 rsurface.batchtvector3f_vertexbuffer = NULL;
10366                 rsurface.batchtvector3f_bufferoffset = 0;
10367                 rsurface.batchnormal3f = NULL;
10368                 rsurface.batchnormal3f_vertexbuffer = NULL;
10369                 rsurface.batchnormal3f_bufferoffset = 0;
10370                 rsurface.batchlightmapcolor4f = NULL;
10371                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10372                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10373                 rsurface.batchtexcoordtexture2f = NULL;
10374                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10375                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10376                 rsurface.batchtexcoordlightmap2f = NULL;
10377                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10378                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10379                 rsurface.batchelement3i = rsurface.array_batchelement3i;
10380                 rsurface.batchelement3i_indexbuffer = NULL;
10381                 rsurface.batchelement3i_bufferoffset = 0;
10382                 rsurface.batchelement3s = NULL;
10383                 rsurface.batchelement3s_indexbuffer = NULL;
10384                 rsurface.batchelement3s_bufferoffset = 0;
10385                 // we'll only be setting up certain arrays as needed
10386                 if (batchneed & BATCHNEED_VERTEXPOSITION)
10387                         rsurface.batchvertexposition = rsurface.array_batchvertexposition;
10388                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10389                         rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
10390                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
10391                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
10392                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
10393                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
10394                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
10395                 {
10396                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
10397                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
10398                 }
10399                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
10400                         rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
10401                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
10402                         rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
10403                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
10404                         rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
10405                 numvertices = 0;
10406                 numtriangles = 0;
10407                 for (i = 0;i < texturenumsurfaces;i++)
10408                 {
10409                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
10410                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
10411                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
10412                         surfaceadjustvertex = numvertices - surfacefirstvertex;
10413                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
10414                         // copy only the data requested
10415                         if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
10416                                 memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
10417                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
10418                                 memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
10419                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
10420                         {
10421                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
10422                                         memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
10423                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
10424                                         memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
10425                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
10426                                 {
10427                                         memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
10428                                         memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
10429                                 }
10430                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
10431                                         memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
10432                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
10433                                         memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
10434                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
10435                                         memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
10436                         }
10437                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
10438                         numvertices += surfacenumvertices;
10439                         numtriangles += surfacenumtriangles;
10440                 }
10441
10442                 // generate a 16bit index array as well if possible
10443                 // (in general, dynamic batches fit)
10444                 if (numvertices <= 65536)
10445                 {
10446                         rsurface.batchelement3s = rsurface.array_batchelement3s;
10447                         for (i = 0;i < numtriangles*3;i++)
10448                                 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
10449                 }
10450
10451                 // since we've copied everything, the batch now starts at 0
10452                 rsurface.batchfirstvertex = 0;
10453                 rsurface.batchnumvertices = numvertices;
10454                 rsurface.batchfirsttriangle = 0;
10455                 rsurface.batchnumtriangles = numtriangles;
10456         }
10457
10458         // q1bsp surfaces rendered in vertex color mode have to have colors
10459         // calculated based on lightstyles
10460         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
10461         {
10462                 // generate color arrays for the surfaces in this list
10463                 int c[4];
10464                 int scale;
10465                 int size3;
10466                 const int *offsets;
10467                 const unsigned char *lm;
10468                 numvertices = 0;
10469                 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
10470                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10471                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10472                 for (i = 0;i < texturenumsurfaces;i++)
10473                 {
10474                         surface = texturesurfacelist[i];
10475                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
10476                         surfacenumvertices = surface->num_vertices;
10477                         if (surface->lightmapinfo->samples)
10478                         {
10479                                 for (j = 0;j < surfacenumvertices;j++)
10480                                 {
10481                                         lm = surface->lightmapinfo->samples + offsets[j];
10482                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
10483                                         VectorScale(lm, scale, c);
10484                                         if (surface->lightmapinfo->styles[1] != 255)
10485                                         {
10486                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
10487                                                 lm += size3;
10488                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
10489                                                 VectorMA(c, scale, lm, c);
10490                                                 if (surface->lightmapinfo->styles[2] != 255)
10491                                                 {
10492                                                         lm += size3;
10493                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
10494                                                         VectorMA(c, scale, lm, c);
10495                                                         if (surface->lightmapinfo->styles[3] != 255)
10496                                                         {
10497                                                                 lm += size3;
10498                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
10499                                                                 VectorMA(c, scale, lm, c);
10500                                                         }
10501                                                 }
10502                                         }
10503                                         c[0] >>= 15;
10504                                         c[1] >>= 15;
10505                                         c[2] >>= 15;
10506                                         Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, min(c[0], 255) * (1.0f / 255.0f), min(c[1], 255) * (1.0f / 255.0f), min(c[2], 255) * (1.0f / 255.0f), 1);
10507                                         numvertices++;
10508                                 }
10509                         }
10510                         else
10511                         {
10512                                 for (j = 0;j < surfacenumvertices;j++)
10513                                 {
10514                                         Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
10515                                         numvertices++;
10516                                 }
10517                         }
10518                 }
10519         }
10520
10521         // if vertices are deformed (sprite flares and things in maps, possibly
10522         // water waves, bulges and other deformations), modify the copied vertices
10523         // in place
10524         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
10525         {
10526                 switch (deform->deform)
10527                 {
10528                 default:
10529                 case Q3DEFORM_PROJECTIONSHADOW:
10530                 case Q3DEFORM_TEXT0:
10531                 case Q3DEFORM_TEXT1:
10532                 case Q3DEFORM_TEXT2:
10533                 case Q3DEFORM_TEXT3:
10534                 case Q3DEFORM_TEXT4:
10535                 case Q3DEFORM_TEXT5:
10536                 case Q3DEFORM_TEXT6:
10537                 case Q3DEFORM_TEXT7:
10538                 case Q3DEFORM_NONE:
10539                         break;
10540                 case Q3DEFORM_AUTOSPRITE:
10541                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
10542                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
10543                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
10544                         VectorNormalize(newforward);
10545                         VectorNormalize(newright);
10546                         VectorNormalize(newup);
10547                         // a single autosprite surface can contain multiple sprites...
10548                         for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
10549                         {
10550                                 VectorClear(center);
10551                                 for (i = 0;i < 4;i++)
10552                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
10553                                 VectorScale(center, 0.25f, center);
10554                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
10555                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
10556                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
10557                                 for (i = 0;i < 4;i++)
10558                                 {
10559                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
10560                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
10561                                 }
10562                         }
10563                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
10564                         Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
10565                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
10566                         rsurface.batchvertex3f_vertexbuffer = NULL;
10567                         rsurface.batchvertex3f_bufferoffset = 0;
10568                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
10569                         rsurface.batchsvector3f_vertexbuffer = NULL;
10570                         rsurface.batchsvector3f_bufferoffset = 0;
10571                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
10572                         rsurface.batchtvector3f_vertexbuffer = NULL;
10573                         rsurface.batchtvector3f_bufferoffset = 0;
10574                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
10575                         rsurface.batchnormal3f_vertexbuffer = NULL;
10576                         rsurface.batchnormal3f_bufferoffset = 0;
10577                         break;
10578                 case Q3DEFORM_AUTOSPRITE2:
10579                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
10580                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
10581                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
10582                         VectorNormalize(newforward);
10583                         VectorNormalize(newright);
10584                         VectorNormalize(newup);
10585                         {
10586                                 const float *v1, *v2;
10587                                 vec3_t start, end;
10588                                 float f, l;
10589                                 struct
10590                                 {
10591                                         float length2;
10592                                         const float *v1;
10593                                         const float *v2;
10594                                 }
10595                                 shortest[2];
10596                                 memset(shortest, 0, sizeof(shortest));
10597                                 // a single autosprite surface can contain multiple sprites...
10598                                 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
10599                                 {
10600                                         VectorClear(center);
10601                                         for (i = 0;i < 4;i++)
10602                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
10603                                         VectorScale(center, 0.25f, center);
10604                                         // find the two shortest edges, then use them to define the
10605                                         // axis vectors for rotating around the central axis
10606                                         for (i = 0;i < 6;i++)
10607                                         {
10608                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
10609                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
10610                                                 l = VectorDistance2(v1, v2);
10611                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
10612                                                 if (v1[2] != v2[2])
10613                                                         l += (1.0f / 1024.0f);
10614                                                 if (shortest[0].length2 > l || i == 0)
10615                                                 {
10616                                                         shortest[1] = shortest[0];
10617                                                         shortest[0].length2 = l;
10618                                                         shortest[0].v1 = v1;
10619                                                         shortest[0].v2 = v2;
10620                                                 }
10621                                                 else if (shortest[1].length2 > l || i == 1)
10622                                                 {
10623                                                         shortest[1].length2 = l;
10624                                                         shortest[1].v1 = v1;
10625                                                         shortest[1].v2 = v2;
10626                                                 }
10627                                         }
10628                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
10629                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
10630                                         // this calculates the right vector from the shortest edge
10631                                         // and the up vector from the edge midpoints
10632                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
10633                                         VectorNormalize(right);
10634                                         VectorSubtract(end, start, up);
10635                                         VectorNormalize(up);
10636                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
10637                                         VectorSubtract(rsurface.localvieworigin, center, forward);
10638                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
10639                                         VectorNegate(forward, forward);
10640                                         VectorReflect(forward, 0, up, forward);
10641                                         VectorNormalize(forward);
10642                                         CrossProduct(up, forward, newright);
10643                                         VectorNormalize(newright);
10644                                         // rotate the quad around the up axis vector, this is made
10645                                         // especially easy by the fact we know the quad is flat,
10646                                         // so we only have to subtract the center position and
10647                                         // measure distance along the right vector, and then
10648                                         // multiply that by the newright vector and add back the
10649                                         // center position
10650                                         // we also need to subtract the old position to undo the
10651                                         // displacement from the center, which we do with a
10652                                         // DotProduct, the subtraction/addition of center is also
10653                                         // optimized into DotProducts here
10654                                         l = DotProduct(right, center);
10655                                         for (i = 0;i < 4;i++)
10656                                         {
10657                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
10658                                                 f = DotProduct(right, v1) - l;
10659                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
10660                                         }
10661                                 }
10662                         }
10663                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
10664                         Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
10665                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
10666                         rsurface.batchvertex3f_vertexbuffer = NULL;
10667                         rsurface.batchvertex3f_bufferoffset = 0;
10668                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
10669                         rsurface.batchsvector3f_vertexbuffer = NULL;
10670                         rsurface.batchsvector3f_bufferoffset = 0;
10671                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
10672                         rsurface.batchtvector3f_vertexbuffer = NULL;
10673                         rsurface.batchtvector3f_bufferoffset = 0;
10674                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
10675                         rsurface.batchnormal3f_vertexbuffer = NULL;
10676                         rsurface.batchnormal3f_bufferoffset = 0;
10677                         break;
10678                 case Q3DEFORM_NORMAL:
10679                         // deform the normals to make reflections wavey
10680                         for (j = 0;j < rsurface.batchnumvertices;j++)
10681                         {
10682                                 float vertex[3];
10683                                 float *normal = rsurface.array_batchnormal3f + 3*j;
10684                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
10685                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
10686                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
10687                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
10688                                 VectorNormalize(normal);
10689                         }
10690                         Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
10691                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
10692                         rsurface.batchsvector3f_vertexbuffer = NULL;
10693                         rsurface.batchsvector3f_bufferoffset = 0;
10694                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
10695                         rsurface.batchtvector3f_vertexbuffer = NULL;
10696                         rsurface.batchtvector3f_bufferoffset = 0;
10697                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
10698                         rsurface.batchnormal3f_vertexbuffer = NULL;
10699                         rsurface.batchnormal3f_bufferoffset = 0;
10700                         break;
10701                 case Q3DEFORM_WAVE:
10702                         // deform vertex array to make wavey water and flags and such
10703                         waveparms[0] = deform->waveparms[0];
10704                         waveparms[1] = deform->waveparms[1];
10705                         waveparms[2] = deform->waveparms[2];
10706                         waveparms[3] = deform->waveparms[3];
10707                         // this is how a divisor of vertex influence on deformation
10708                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10709                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10710                         for (j = 0;j < rsurface.batchnumvertices;j++)
10711                         {
10712                                 // if the wavefunc depends on time, evaluate it per-vertex
10713                                 if (waveparms[3])
10714                                 {
10715                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10716                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10717                                 }
10718                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
10719                         }
10720                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
10721                         Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
10722                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
10723                         rsurface.batchvertex3f_vertexbuffer = NULL;
10724                         rsurface.batchvertex3f_bufferoffset = 0;
10725                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
10726                         rsurface.batchsvector3f_vertexbuffer = NULL;
10727                         rsurface.batchsvector3f_bufferoffset = 0;
10728                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
10729                         rsurface.batchtvector3f_vertexbuffer = NULL;
10730                         rsurface.batchtvector3f_bufferoffset = 0;
10731                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
10732                         rsurface.batchnormal3f_vertexbuffer = NULL;
10733                         rsurface.batchnormal3f_bufferoffset = 0;
10734                         break;
10735                 case Q3DEFORM_BULGE:
10736                         // deform vertex array to make the surface have moving bulges
10737                         for (j = 0;j < rsurface.batchnumvertices;j++)
10738                         {
10739                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
10740                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
10741                         }
10742                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
10743                         Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
10744                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
10745                         rsurface.batchvertex3f_vertexbuffer = NULL;
10746                         rsurface.batchvertex3f_bufferoffset = 0;
10747                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
10748                         rsurface.batchsvector3f_vertexbuffer = NULL;
10749                         rsurface.batchsvector3f_bufferoffset = 0;
10750                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
10751                         rsurface.batchtvector3f_vertexbuffer = NULL;
10752                         rsurface.batchtvector3f_bufferoffset = 0;
10753                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
10754                         rsurface.batchnormal3f_vertexbuffer = NULL;
10755                         rsurface.batchnormal3f_bufferoffset = 0;
10756                         break;
10757                 case Q3DEFORM_MOVE:
10758                         // deform vertex array
10759                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10760                         VectorScale(deform->parms, scale, waveparms);
10761                         for (j = 0;j < rsurface.batchnumvertices;j++)
10762                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
10763                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
10764                         rsurface.batchvertex3f_vertexbuffer = NULL;
10765                         rsurface.batchvertex3f_bufferoffset = 0;
10766                         break;
10767                 }
10768         }
10769
10770         // generate texcoords based on the chosen texcoord source
10771         switch(rsurface.texture->tcgen.tcgen)
10772         {
10773         default:
10774         case Q3TCGEN_TEXTURE:
10775                 break;
10776         case Q3TCGEN_LIGHTMAP:
10777                 if (rsurface.batchtexcoordlightmap2f)
10778                         memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
10779                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
10780                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10781                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10782                 break;
10783         case Q3TCGEN_VECTOR:
10784                 for (j = 0;j < rsurface.batchnumvertices;j++)
10785                 {
10786                         rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
10787                         rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
10788                 }
10789                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
10790                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10791                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10792                 break;
10793         case Q3TCGEN_ENVIRONMENT:
10794                 // make environment reflections using a spheremap
10795                 for (j = 0;j < rsurface.batchnumvertices;j++)
10796                 {
10797                         // identical to Q3A's method, but executed in worldspace so
10798                         // carried models can be shiny too
10799
10800                         float viewer[3], d, reflected[3], worldreflected[3];
10801
10802                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10803                         // VectorNormalize(viewer);
10804
10805                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10806
10807                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10808                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10809                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10810                         // note: this is proportinal to viewer, so we can normalize later
10811
10812                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10813                         VectorNormalize(worldreflected);
10814
10815                         // note: this sphere map only uses world x and z!
10816                         // so positive and negative y will LOOK THE SAME.
10817                         rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10818                         rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10819                 }
10820                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
10821                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10822                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10823                 break;
10824         }
10825         // the only tcmod that needs software vertex processing is turbulent, so
10826         // check for it here and apply the changes if needed
10827         // and we only support that as the first one
10828         // (handling a mixture of turbulent and other tcmods would be problematic
10829         //  without punting it entirely to a software path)
10830         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10831         {
10832                 amplitude = rsurface.texture->tcmods[0].parms[1];
10833                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
10834                 for (j = 0;j < rsurface.batchnumvertices;j++)
10835                 {
10836                         rsurface.array_batchtexcoordtexture2f[j*2+0] += amplitude * sin(((rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10837                         rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10838                 }
10839                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
10840                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10841                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10842         }
10843
10844         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10845         {
10846                 // convert the modified arrays to vertex structs
10847                 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
10848                 rsurface.batchvertexmeshbuffer = NULL;
10849                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10850                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
10851                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10852                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10853                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
10854                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10855                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10856                 {
10857                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
10858                         {
10859                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10860                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10861                         }
10862                 }
10863                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10864                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
10865                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
10866                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10867                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
10868                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10869                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10870                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
10871                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10872         }
10873
10874         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
10875         {
10876                 // convert the modified arrays to vertex structs
10877                 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
10878                 rsurface.batchvertexpositionbuffer = NULL;
10879                 if (sizeof(r_vertexposition_t) == sizeof(float[3]))
10880                         memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
10881                 else
10882                         for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
10883                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
10884         }
10885 }
10886
10887 void RSurf_DrawBatch(void)
10888 {
10889         R_Mesh_Draw(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchfirsttriangle, rsurface.batchnumtriangles, rsurface.batchelement3i, rsurface.batchelement3i_indexbuffer, rsurface.batchelement3i_bufferoffset, rsurface.batchelement3s, rsurface.batchelement3s_indexbuffer, rsurface.batchelement3s_bufferoffset);
10890 }
10891
10892 static void RSurf_BindLightmapForBatch(void)
10893 {
10894         switch(vid.renderpath)
10895         {
10896         case RENDERPATH_CGGL:
10897 #ifdef SUPPORTCG
10898                 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , rsurface.lightmaptexture );CHECKCGERROR
10899                 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, rsurface.deluxemaptexture);CHECKCGERROR
10900 #endif
10901                 break;
10902         case RENDERPATH_GL20:
10903                 if (r_glsl_permutation->loc_Texture_Lightmap  >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture );
10904                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, rsurface.deluxemaptexture);
10905                 break;
10906         case RENDERPATH_GL13:
10907         case RENDERPATH_GL11:
10908                 R_Mesh_TexBind(0, rsurface.lightmaptexture);
10909                 break;
10910         }
10911 }
10912
10913 static void RSurf_BindReflectionForBatch(void)
10914 {
10915         // pick the closest matching water plane and bind textures
10916         int planeindex, vertexindex;
10917         float d, bestd;
10918         vec3_t vert;
10919         const float *v;
10920         r_waterstate_waterplane_t *p, *bestp;
10921         bestd = 0;
10922         bestp = NULL;
10923         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
10924         {
10925                 if(p->camera_entity != rsurface.texture->camera_entity)
10926                         continue;
10927                 d = 0;
10928                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10929                 {
10930                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10931                         d += fabs(PlaneDiff(vert, &p->plane));
10932                 }
10933                 if (bestd > d || !bestp)
10934                 {
10935                         bestd = d;
10936                         bestp = p;
10937                 }
10938         }
10939         switch(vid.renderpath)
10940         {
10941         case RENDERPATH_CGGL:
10942 #ifdef SUPPORTCG
10943                 if (r_cg_permutation->fp_Texture_Refraction) {CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR}
10944                 else if (r_cg_permutation->fp_Texture_First) {CG_BindTexture(r_cg_permutation->fp_Texture_First, bestp ? bestp->texture_camera : r_texture_black);CHECKCGERROR}
10945                 if (r_cg_permutation->fp_Texture_Reflection) {CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR}
10946 #endif
10947                 break;
10948         case RENDERPATH_GL20:
10949                 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
10950                 else if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST, bestp ? bestp->texture_camera : r_texture_black);
10951                 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
10952                 break;
10953         case RENDERPATH_GL13:
10954         case RENDERPATH_GL11:
10955                 break;
10956         }
10957 }
10958
10959 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10960 {
10961         int i;
10962         for (i = 0;i < rsurface.batchnumvertices;i++)
10963                 Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10964         rsurface.passcolor4f = rsurface.array_passcolor4f;
10965         rsurface.passcolor4f_vertexbuffer = 0;
10966         rsurface.passcolor4f_bufferoffset = 0;
10967 }
10968
10969 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10970 {
10971         int i;
10972         float f;
10973         const float *v;
10974         const float *c;
10975         float *c2;
10976         if (rsurface.passcolor4f)
10977         {
10978                 // generate color arrays
10979                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
10980                 {
10981                         f = RSurf_FogVertex(v);
10982                         c2[0] = c[0] * f;
10983                         c2[1] = c[1] * f;
10984                         c2[2] = c[2] * f;
10985                         c2[3] = c[3];
10986                 }
10987         }
10988         else
10989         {
10990                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10991                 {
10992                         f = RSurf_FogVertex(v);
10993                         c2[0] = f;
10994                         c2[1] = f;
10995                         c2[2] = f;
10996                         c2[3] = 1;
10997                 }
10998         }
10999         rsurface.passcolor4f = rsurface.array_passcolor4f;
11000         rsurface.passcolor4f_vertexbuffer = 0;
11001         rsurface.passcolor4f_bufferoffset = 0;
11002 }
11003
11004 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
11005 {
11006         int i;
11007         float f;
11008         const float *v;
11009         const float *c;
11010         float *c2;
11011         if (!rsurface.passcolor4f)
11012                 return;
11013         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
11014         {
11015                 f = RSurf_FogVertex(v);
11016                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
11017                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
11018                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
11019                 c2[3] = c[3];
11020         }
11021         rsurface.passcolor4f = rsurface.array_passcolor4f;
11022         rsurface.passcolor4f_vertexbuffer = 0;
11023         rsurface.passcolor4f_bufferoffset = 0;
11024 }
11025
11026 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
11027 {
11028         int i;
11029         const float *c;
11030         float *c2;
11031         if (!rsurface.passcolor4f)
11032                 return;
11033         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11034         {
11035                 c2[0] = c[0] * r;
11036                 c2[1] = c[1] * g;
11037                 c2[2] = c[2] * b;
11038                 c2[3] = c[3] * a;
11039         }
11040         rsurface.passcolor4f = rsurface.array_passcolor4f;
11041         rsurface.passcolor4f_vertexbuffer = 0;
11042         rsurface.passcolor4f_bufferoffset = 0;
11043 }
11044
11045 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
11046 {
11047         int i;
11048         const float *c;
11049         float *c2;
11050         if (!rsurface.passcolor4f)
11051                 return;
11052         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11053         {
11054                 c2[0] = c[0] + r_refdef.scene.ambient;
11055                 c2[1] = c[1] + r_refdef.scene.ambient;
11056                 c2[2] = c[2] + r_refdef.scene.ambient;
11057                 c2[3] = c[3];
11058         }
11059         rsurface.passcolor4f = rsurface.array_passcolor4f;
11060         rsurface.passcolor4f_vertexbuffer = 0;
11061         rsurface.passcolor4f_bufferoffset = 0;
11062 }
11063
11064 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11065 {
11066         // TODO: optimize
11067         rsurface.passcolor4f = NULL;
11068         rsurface.passcolor4f_vertexbuffer = 0;
11069         rsurface.passcolor4f_bufferoffset = 0;
11070         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11071         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11072         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11073         GL_Color(r, g, b, a);
11074         RSurf_BindLightmapForBatch();
11075         RSurf_DrawBatch();
11076 }
11077
11078 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11079 {
11080         // TODO: optimize applyfog && applycolor case
11081         // just apply fog if necessary, and tint the fog color array if necessary
11082         rsurface.passcolor4f = NULL;
11083         rsurface.passcolor4f_vertexbuffer = 0;
11084         rsurface.passcolor4f_bufferoffset = 0;
11085         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11086         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11087         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11088         GL_Color(r, g, b, a);
11089         RSurf_DrawBatch();
11090 }
11091
11092 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11093 {
11094         // TODO: optimize
11095         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11096         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11097         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11098         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11099         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11100         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11101         GL_Color(r, g, b, a);
11102         RSurf_DrawBatch();
11103 }
11104
11105 static void RSurf_DrawBatch_GL11_ClampColor(void)
11106 {
11107         int i;
11108         const float *c1;
11109         float *c2;
11110         if (!rsurface.passcolor4f)
11111                 return;
11112         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
11113         {
11114                 c2[0] = bound(0.0f, c1[0], 1.0f);
11115                 c2[1] = bound(0.0f, c1[1], 1.0f);
11116                 c2[2] = bound(0.0f, c1[2], 1.0f);
11117                 c2[3] = bound(0.0f, c1[3], 1.0f);
11118         }
11119 }
11120
11121 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
11122 {
11123         int i;
11124         float f;
11125         float alpha;
11126         const float *v;
11127         const float *n;
11128         float *c;
11129         vec3_t ambientcolor;
11130         vec3_t diffusecolor;
11131         vec3_t lightdir;
11132         // TODO: optimize
11133         // model lighting
11134         VectorCopy(rsurface.modellight_lightdir, lightdir);
11135         f = 0.5f * r_refdef.lightmapintensity;
11136         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
11137         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
11138         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
11139         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
11140         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
11141         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
11142         alpha = *a;
11143         if (VectorLength2(diffusecolor) > 0)
11144         {
11145                 // q3-style directional shading
11146                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
11147                 {
11148                         if ((f = DotProduct(n, lightdir)) > 0)
11149                                 VectorMA(ambientcolor, f, diffusecolor, c);
11150                         else
11151                                 VectorCopy(ambientcolor, c);
11152                         c[3] = alpha;
11153                 }
11154                 *r = 1;
11155                 *g = 1;
11156                 *b = 1;
11157                 *a = 1;
11158                 rsurface.passcolor4f = rsurface.array_passcolor4f;
11159                 rsurface.passcolor4f_vertexbuffer = 0;
11160                 rsurface.passcolor4f_bufferoffset = 0;
11161                 *applycolor = false;
11162         }
11163         else
11164         {
11165                 *r = ambientcolor[0];
11166                 *g = ambientcolor[1];
11167                 *b = ambientcolor[2];
11168                 rsurface.passcolor4f = NULL;
11169                 rsurface.passcolor4f_vertexbuffer = 0;
11170                 rsurface.passcolor4f_bufferoffset = 0;
11171         }
11172 }
11173
11174 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11175 {
11176         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
11177         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11178         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11179         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11180         GL_Color(r, g, b, a);
11181         RSurf_DrawBatch();
11182 }
11183
11184 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
11185 {
11186         int i;
11187         float f;
11188         const float *v;
11189         float *c;
11190         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
11191         {
11192                 f = 1 - RSurf_FogVertex(v);
11193                 c[0] = r;
11194                 c[1] = g;
11195                 c[2] = b;
11196                 c[3] = f * a;
11197         }
11198 }
11199
11200 void RSurf_SetupDepthAndCulling(void)
11201 {
11202         // submodels are biased to avoid z-fighting with world surfaces that they
11203         // may be exactly overlapping (avoids z-fighting artifacts on certain
11204         // doors and things in Quake maps)
11205         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
11206         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
11207         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
11208         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11209 }
11210
11211 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11212 {
11213         // transparent sky would be ridiculous
11214         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11215                 return;
11216         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11217         skyrenderlater = true;
11218         RSurf_SetupDepthAndCulling();
11219         GL_DepthMask(true);
11220         // LordHavoc: HalfLife maps have freaky skypolys so don't use
11221         // skymasking on them, and Quake3 never did sky masking (unlike
11222         // software Quake and software Quake2), so disable the sky masking
11223         // in Quake3 maps as it causes problems with q3map2 sky tricks,
11224         // and skymasking also looks very bad when noclipping outside the
11225         // level, so don't use it then either.
11226         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
11227         {
11228                 R_Mesh_ResetTextureState();
11229                 if (skyrendermasked)
11230                 {
11231                         R_SetupShader_DepthOrShadow();
11232                         // depth-only (masking)
11233                         GL_ColorMask(0,0,0,0);
11234                         // just to make sure that braindead drivers don't draw
11235                         // anything despite that colormask...
11236                         GL_BlendFunc(GL_ZERO, GL_ONE);
11237                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
11238                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
11239                 }
11240                 else
11241                 {
11242                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11243                         // fog sky
11244                         GL_BlendFunc(GL_ONE, GL_ZERO);
11245                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
11246                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
11247                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11248                 }
11249                 RSurf_DrawBatch();
11250                 if (skyrendermasked)
11251                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11252         }
11253         R_Mesh_ResetTextureState();
11254         GL_Color(1, 1, 1, 1);
11255 }
11256
11257 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
11258 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
11259 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11260 {
11261         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
11262                 return;
11263         if (prepass)
11264         {
11265                 // render screenspace normalmap to texture
11266                 GL_DepthMask(true);
11267                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist);
11268                 RSurf_DrawBatch();
11269         }
11270         else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
11271         {
11272                 // render water or distortion background, then blend surface on top
11273                 GL_DepthMask(true);
11274                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, texturenumsurfaces, texturesurfacelist);
11275                 RSurf_BindReflectionForBatch();
11276                 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
11277                         RSurf_BindLightmapForBatch();
11278                 RSurf_DrawBatch();
11279                 GL_DepthMask(false);
11280                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist);
11281                 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
11282                         RSurf_BindLightmapForBatch();
11283                 RSurf_DrawBatch();
11284         }
11285         else
11286         {
11287                 // render surface normally
11288                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
11289                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist);
11290                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
11291                         RSurf_BindReflectionForBatch();
11292                 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
11293                         RSurf_BindLightmapForBatch();
11294                 RSurf_DrawBatch();
11295         }
11296 }
11297
11298 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11299 {
11300         // OpenGL 1.3 path - anything not completely ancient
11301         qboolean applycolor;
11302         qboolean applyfog;
11303         int layerindex;
11304         const texturelayer_t *layer;
11305         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11306         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11307
11308         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
11309         {
11310                 vec4_t layercolor;
11311                 int layertexrgbscale;
11312                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11313                 {
11314                         if (layerindex == 0)
11315                                 GL_AlphaTest(true);
11316                         else
11317                         {
11318                                 GL_AlphaTest(false);
11319                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
11320                         }
11321                 }
11322                 GL_DepthMask(layer->depthmask && writedepth);
11323                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
11324                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
11325                 {
11326                         layertexrgbscale = 4;
11327                         VectorScale(layer->color, 0.25f, layercolor);
11328                 }
11329                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
11330                 {
11331                         layertexrgbscale = 2;
11332                         VectorScale(layer->color, 0.5f, layercolor);
11333                 }
11334                 else
11335                 {
11336                         layertexrgbscale = 1;
11337                         VectorScale(layer->color, 1.0f, layercolor);
11338                 }
11339                 layercolor[3] = layer->color[3];
11340                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
11341                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
11342                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
11343                 switch (layer->type)
11344                 {
11345                 case TEXTURELAYERTYPE_LITTEXTURE:
11346                         // single-pass lightmapped texture with 2x rgbscale
11347                         R_Mesh_TexBind(0, r_texture_white);
11348                         R_Mesh_TexMatrix(0, NULL);
11349                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11350                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
11351                         R_Mesh_TexBind(1, layer->texture);
11352                         R_Mesh_TexMatrix(1, &layer->texmatrix);
11353                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11354                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11355                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11356                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11357                         else if (rsurface.uselightmaptexture)
11358                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11359                         else
11360                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11361                         break;
11362                 case TEXTURELAYERTYPE_TEXTURE:
11363                         // singletexture unlit texture with transparency support
11364                         R_Mesh_TexBind(0, layer->texture);
11365                         R_Mesh_TexMatrix(0, &layer->texmatrix);
11366                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11367                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11368                         R_Mesh_TexBind(1, 0);
11369                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11370                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11371                         break;
11372                 case TEXTURELAYERTYPE_FOG:
11373                         // singletexture fogging
11374                         if (layer->texture)
11375                         {
11376                                 R_Mesh_TexBind(0, layer->texture);
11377                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11378                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11379                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11380                         }
11381                         else
11382                         {
11383                                 R_Mesh_TexBind(0, 0);
11384                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11385                         }
11386                         R_Mesh_TexBind(1, 0);
11387                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11388                         // generate a color array for the fog pass
11389                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
11390                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
11391                         RSurf_DrawBatch();
11392                         break;
11393                 default:
11394                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11395                 }
11396         }
11397         CHECKGLERROR
11398         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11399         {
11400                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
11401                 GL_AlphaTest(false);
11402         }
11403 }
11404
11405 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11406 {
11407         // OpenGL 1.1 - crusty old voodoo path
11408         qboolean applyfog;
11409         int layerindex;
11410         const texturelayer_t *layer;
11411         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11412         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11413
11414         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
11415         {
11416                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11417                 {
11418                         if (layerindex == 0)
11419                                 GL_AlphaTest(true);
11420                         else
11421                         {
11422                                 GL_AlphaTest(false);
11423                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
11424                         }
11425                 }
11426                 GL_DepthMask(layer->depthmask && writedepth);
11427                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
11428                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
11429                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
11430                 switch (layer->type)
11431                 {
11432                 case TEXTURELAYERTYPE_LITTEXTURE:
11433                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
11434                         {
11435                                 // two-pass lit texture with 2x rgbscale
11436                                 // first the lightmap pass
11437                                 R_Mesh_TexBind(0, r_texture_white);
11438                                 R_Mesh_TexMatrix(0, NULL);
11439                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11440                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
11441                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11442                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
11443                                 else if (rsurface.uselightmaptexture)
11444                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
11445                                 else
11446                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
11447                                 // then apply the texture to it
11448                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
11449                                 R_Mesh_TexBind(0, layer->texture);
11450                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11451                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11452                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11453                                 RSurf_DrawBatch_GL11_Unlit(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);
11454                         }
11455                         else
11456                         {
11457                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
11458                                 R_Mesh_TexBind(0, layer->texture);
11459                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11460                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11461                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11462                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11463                                         RSurf_DrawBatch_GL11_VertexShade(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);
11464                                 else
11465                                         RSurf_DrawBatch_GL11_VertexColor(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);
11466                         }
11467                         break;
11468                 case TEXTURELAYERTYPE_TEXTURE:
11469                         // singletexture unlit texture with transparency support
11470                         R_Mesh_TexBind(0, layer->texture);
11471                         R_Mesh_TexMatrix(0, &layer->texmatrix);
11472                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11473                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11474                         RSurf_DrawBatch_GL11_Unlit(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);
11475                         break;
11476                 case TEXTURELAYERTYPE_FOG:
11477                         // singletexture fogging
11478                         if (layer->texture)
11479                         {
11480                                 R_Mesh_TexBind(0, layer->texture);
11481                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11482                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11483                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11484                         }
11485                         else
11486                         {
11487                                 R_Mesh_TexBind(0, 0);
11488                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11489                         }
11490                         // generate a color array for the fog pass
11491                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
11492                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
11493                         RSurf_DrawBatch();
11494                         break;
11495                 default:
11496                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11497                 }
11498         }
11499         CHECKGLERROR
11500         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11501         {
11502                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
11503                 GL_AlphaTest(false);
11504         }
11505 }
11506
11507 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11508 {
11509         int vi;
11510         int j;
11511         r_vertexgeneric_t *batchvertex;
11512         float c[4];
11513
11514         GL_AlphaTest(false);
11515         R_Mesh_ResetTextureState();
11516         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11517
11518         if(rsurface.texture && rsurface.texture->currentskinframe)
11519         {
11520                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11521                 c[3] *= rsurface.texture->currentalpha;
11522         }
11523         else
11524         {
11525                 c[0] = 1;
11526                 c[1] = 0;
11527                 c[2] = 1;
11528                 c[3] = 1;
11529         }
11530
11531         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11532         {
11533                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11534                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11535                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11536         }
11537
11538         // brighten it up (as texture value 127 means "unlit")
11539         c[0] *= 2 * r_refdef.view.colorscale;
11540         c[1] *= 2 * r_refdef.view.colorscale;
11541         c[2] *= 2 * r_refdef.view.colorscale;
11542
11543         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11544                 c[3] *= r_wateralpha.value;
11545
11546         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11547         {
11548                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11549                 GL_DepthMask(false);
11550         }
11551         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11552         {
11553                 GL_BlendFunc(GL_ONE, GL_ONE);
11554                 GL_DepthMask(false);
11555         }
11556         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11557         {
11558                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11559                 GL_DepthMask(false);
11560         }
11561         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11562         {
11563                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11564                 GL_DepthMask(false);
11565         }
11566         else
11567         {
11568                 GL_BlendFunc(GL_ONE, GL_ZERO);
11569                 GL_DepthMask(writedepth);
11570         }
11571
11572         if (r_showsurfaces.integer == 3)
11573         {
11574                 rsurface.passcolor4f = NULL;
11575
11576                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11577                 {
11578                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11579
11580                         rsurface.passcolor4f = NULL;
11581                         rsurface.passcolor4f_vertexbuffer = 0;
11582                         rsurface.passcolor4f_bufferoffset = 0;
11583                 }
11584                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11585                 {
11586                         qboolean applycolor = true;
11587                         float one = 1.0;
11588
11589                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11590
11591                         r_refdef.lightmapintensity = 1;
11592                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11593                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11594                 }
11595                 else
11596                 {
11597                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11598
11599                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11600                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11601                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11602                 }
11603
11604                 if(!rsurface.passcolor4f)
11605                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11606
11607                 RSurf_DrawBatch_GL11_ApplyAmbient();
11608                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11609                 if(r_refdef.fogenabled)
11610                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11611                 RSurf_DrawBatch_GL11_ClampColor();
11612
11613                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11614                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11615                 RSurf_DrawBatch();
11616         }
11617         else if (!r_refdef.view.showdebug)
11618         {
11619                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11620                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11621                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
11622                 {
11623                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11624                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
11625                 }
11626                 R_Mesh_PrepareVertices_Generic_Unlock();
11627                 RSurf_DrawBatch();
11628         }
11629         else if (r_showsurfaces.integer == 4)
11630         {
11631                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11632                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11633                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
11634                 {
11635                         unsigned char c = vi << 3;
11636                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11637                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
11638                 }
11639                 R_Mesh_PrepareVertices_Generic_Unlock();
11640                 RSurf_DrawBatch();
11641         }
11642         else if (r_showsurfaces.integer == 2)
11643         {
11644                 const int *e;
11645                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11646                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11647                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11648                 {
11649                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
11650                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11651                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11652                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11653                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
11654                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
11655                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
11656                 }
11657                 R_Mesh_PrepareVertices_Generic_Unlock();
11658                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11659         }
11660         else
11661         {
11662                 int texturesurfaceindex;
11663                 int k;
11664                 const msurface_t *surface;
11665                 unsigned char surfacecolor4ub[4];
11666                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11667                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11668                 vi = 0;
11669                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11670                 {
11671                         surface = texturesurfacelist[texturesurfaceindex];
11672                         k = (int)(((size_t)surface) / sizeof(msurface_t));
11673                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
11674                         for (j = 0;j < surface->num_vertices;j++)
11675                         {
11676                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11677                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
11678                                 vi++;
11679                         }
11680                 }
11681                 R_Mesh_PrepareVertices_Generic_Unlock();
11682                 RSurf_DrawBatch();
11683         }
11684 }
11685
11686 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11687 {
11688         CHECKGLERROR
11689         RSurf_SetupDepthAndCulling();
11690         if (r_showsurfaces.integer)
11691         {
11692                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11693                 return;
11694         }
11695         switch (vid.renderpath)
11696         {
11697         case RENDERPATH_GL20:
11698         case RENDERPATH_CGGL:
11699                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11700                 break;
11701         case RENDERPATH_GL13:
11702                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11703                 break;
11704         case RENDERPATH_GL11:
11705                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11706                 break;
11707         }
11708         CHECKGLERROR
11709 }
11710
11711 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11712 {
11713         CHECKGLERROR
11714         RSurf_SetupDepthAndCulling();
11715         if (r_showsurfaces.integer)
11716         {
11717                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11718                 return;
11719         }
11720         switch (vid.renderpath)
11721         {
11722         case RENDERPATH_GL20:
11723         case RENDERPATH_CGGL:
11724                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11725                 break;
11726         case RENDERPATH_GL13:
11727                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11728                 break;
11729         case RENDERPATH_GL11:
11730                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11731                 break;
11732         }
11733         CHECKGLERROR
11734 }
11735
11736 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11737 {
11738         int i, j;
11739         int texturenumsurfaces, endsurface;
11740         texture_t *texture;
11741         const msurface_t *surface;
11742 #define MAXBATCH_TRANSPARENTSURFACES 256
11743         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
11744
11745         // if the model is static it doesn't matter what value we give for
11746         // wantnormals and wanttangents, so this logic uses only rules applicable
11747         // to a model, knowing that they are meaningless otherwise
11748         if (ent == r_refdef.scene.worldentity)
11749                 RSurf_ActiveWorldEntity();
11750         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11751                 RSurf_ActiveModelEntity(ent, false, false, false);
11752         else
11753         {
11754                 switch (vid.renderpath)
11755                 {
11756                 case RENDERPATH_GL20:
11757                 case RENDERPATH_CGGL:
11758                         RSurf_ActiveModelEntity(ent, true, true, false);
11759                         break;
11760                 case RENDERPATH_GL13:
11761                 case RENDERPATH_GL11:
11762                         RSurf_ActiveModelEntity(ent, true, false, false);
11763                         break;
11764                 }
11765         }
11766
11767         if (r_transparentdepthmasking.integer)
11768         {
11769                 qboolean setup = false;
11770                 for (i = 0;i < numsurfaces;i = j)
11771                 {
11772                         j = i + 1;
11773                         surface = rsurface.modelsurfaces + surfacelist[i];
11774                         texture = surface->texture;
11775                         rsurface.texture = R_GetCurrentTexture(texture);
11776                         rsurface.lightmaptexture = NULL;
11777                         rsurface.deluxemaptexture = NULL;
11778                         rsurface.uselightmaptexture = false;
11779                         // scan ahead until we find a different texture
11780                         endsurface = min(i + 1024, numsurfaces);
11781                         texturenumsurfaces = 0;
11782                         texturesurfacelist[texturenumsurfaces++] = surface;
11783                         for (;j < endsurface;j++)
11784                         {
11785                                 surface = rsurface.modelsurfaces + surfacelist[j];
11786                                 if (texture != surface->texture)
11787                                         break;
11788                                 texturesurfacelist[texturenumsurfaces++] = surface;
11789                         }
11790                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11791                                 continue;
11792                         // render the range of surfaces as depth
11793                         if (!setup)
11794                         {
11795                                 setup = true;
11796                                 GL_ColorMask(0,0,0,0);
11797                                 GL_Color(1,1,1,1);
11798                                 GL_DepthTest(true);
11799                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11800                                 GL_DepthMask(true);
11801                                 GL_AlphaTest(false);
11802                                 R_Mesh_ResetTextureState();
11803                                 R_SetupShader_DepthOrShadow();
11804                         }
11805                         RSurf_SetupDepthAndCulling();
11806                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
11807                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
11808                         RSurf_DrawBatch();
11809                 }
11810                 if (setup)
11811                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11812         }
11813
11814         for (i = 0;i < numsurfaces;i = j)
11815         {
11816                 j = i + 1;
11817                 surface = rsurface.modelsurfaces + surfacelist[i];
11818                 texture = surface->texture;
11819                 rsurface.texture = R_GetCurrentTexture(texture);
11820                 rsurface.lightmaptexture = surface->lightmaptexture;
11821                 rsurface.deluxemaptexture = surface->deluxemaptexture;
11822                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11823                 // scan ahead until we find a different texture
11824                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
11825                 texturenumsurfaces = 0;
11826                 texturesurfacelist[texturenumsurfaces++] = surface;
11827                 for (;j < endsurface;j++)
11828                 {
11829                         surface = rsurface.modelsurfaces + surfacelist[j];
11830                         if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11831                                 break;
11832                         texturesurfacelist[texturenumsurfaces++] = surface;
11833                 }
11834                 // render the range of surfaces
11835                 if (ent == r_refdef.scene.worldentity)
11836                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11837                 else
11838                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11839         }
11840         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11841         GL_AlphaTest(false);
11842 }
11843
11844 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
11845 {
11846         // transparent surfaces get pushed off into the transparent queue
11847         int surfacelistindex;
11848         const msurface_t *surface;
11849         vec3_t tempcenter, center;
11850         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11851         {
11852                 surface = texturesurfacelist[surfacelistindex];
11853                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11854                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11855                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11856                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11857                 if (queueentity->transparent_offset) // transparent offset
11858                 {
11859                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
11860                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
11861                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
11862                 }
11863                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
11864         }
11865 }
11866
11867 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11868 {
11869         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11870                 return;
11871         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11872                 return;
11873         RSurf_SetupDepthAndCulling();
11874         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
11875         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
11876         RSurf_DrawBatch();
11877 }
11878
11879 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11880 {
11881         const entity_render_t *queueentity = r_refdef.scene.worldentity;
11882         CHECKGLERROR
11883         if (depthonly)
11884                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11885         else if (prepass)
11886         {
11887                 if (!rsurface.texture->currentnumlayers)
11888                         return;
11889                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11890                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11891                 else
11892                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11893         }
11894         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
11895                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11896         else if (!rsurface.texture->currentnumlayers)
11897                 return;
11898         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11899         {
11900                 // in the deferred case, transparent surfaces were queued during prepass
11901                 if (!r_shadow_usingdeferredprepass)
11902                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11903         }
11904         else
11905         {
11906                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11907                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11908         }
11909         CHECKGLERROR
11910 }
11911
11912 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11913 {
11914         int i, j;
11915         texture_t *texture;
11916         // break the surface list down into batches by texture and use of lightmapping
11917         for (i = 0;i < numsurfaces;i = j)
11918         {
11919                 j = i + 1;
11920                 // texture is the base texture pointer, rsurface.texture is the
11921                 // current frame/skin the texture is directing us to use (for example
11922                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11923                 // use skin 1 instead)
11924                 texture = surfacelist[i]->texture;
11925                 rsurface.texture = R_GetCurrentTexture(texture);
11926                 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11927                 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11928                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11929                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11930                 {
11931                         // if this texture is not the kind we want, skip ahead to the next one
11932                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11933                                 ;
11934                         continue;
11935                 }
11936                 // simply scan ahead until we find a different texture or lightmap state
11937                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11938                         ;
11939                 // render the range of surfaces
11940                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11941         }
11942 }
11943
11944 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
11945 {
11946         CHECKGLERROR
11947         if (depthonly)
11948                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11949         else if (prepass)
11950         {
11951                 if (!rsurface.texture->currentnumlayers)
11952                         return;
11953                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11954                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11955                 else
11956                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11957         }
11958         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
11959                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11960         else if (!rsurface.texture->currentnumlayers)
11961                 return;
11962         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11963         {
11964                 // in the deferred case, transparent surfaces were queued during prepass
11965                 if (!r_shadow_usingdeferredprepass)
11966                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11967         }
11968         else
11969         {
11970                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11971                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11972         }
11973         CHECKGLERROR
11974 }
11975
11976 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11977 {
11978         int i, j;
11979         texture_t *texture;
11980         // break the surface list down into batches by texture and use of lightmapping
11981         for (i = 0;i < numsurfaces;i = j)
11982         {
11983                 j = i + 1;
11984                 // texture is the base texture pointer, rsurface.texture is the
11985                 // current frame/skin the texture is directing us to use (for example
11986                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11987                 // use skin 1 instead)
11988                 texture = surfacelist[i]->texture;
11989                 rsurface.texture = R_GetCurrentTexture(texture);
11990                 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11991                 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11992                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11993                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11994                 {
11995                         // if this texture is not the kind we want, skip ahead to the next one
11996                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11997                                 ;
11998                         continue;
11999                 }
12000                 // simply scan ahead until we find a different texture or lightmap state
12001                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12002                         ;
12003                 // render the range of surfaces
12004                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
12005         }
12006 }
12007
12008 float locboxvertex3f[6*4*3] =
12009 {
12010         1,0,1, 1,0,0, 1,1,0, 1,1,1,
12011         0,1,1, 0,1,0, 0,0,0, 0,0,1,
12012         1,1,1, 1,1,0, 0,1,0, 0,1,1,
12013         0,0,1, 0,0,0, 1,0,0, 1,0,1,
12014         0,0,1, 1,0,1, 1,1,1, 0,1,1,
12015         1,0,0, 0,0,0, 0,1,0, 1,1,0
12016 };
12017
12018 unsigned short locboxelements[6*2*3] =
12019 {
12020          0, 1, 2, 0, 2, 3,
12021          4, 5, 6, 4, 6, 7,
12022          8, 9,10, 8,10,11,
12023         12,13,14, 12,14,15,
12024         16,17,18, 16,18,19,
12025         20,21,22, 20,22,23
12026 };
12027
12028 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12029 {
12030         int i, j;
12031         cl_locnode_t *loc = (cl_locnode_t *)ent;
12032         vec3_t mins, size;
12033         float vertex3f[6*4*3];
12034         CHECKGLERROR
12035         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12036         GL_DepthMask(false);
12037         GL_DepthRange(0, 1);
12038         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12039         GL_DepthTest(true);
12040         GL_CullFace(GL_NONE);
12041         R_EntityMatrix(&identitymatrix);
12042
12043         R_Mesh_ResetTextureState();
12044
12045         i = surfacelist[0];
12046         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12047                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12048                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12049                         surfacelist[0] < 0 ? 0.5f : 0.125f);
12050
12051         if (VectorCompare(loc->mins, loc->maxs))
12052         {
12053                 VectorSet(size, 2, 2, 2);
12054                 VectorMA(loc->mins, -0.5f, size, mins);
12055         }
12056         else
12057         {
12058                 VectorCopy(loc->mins, mins);
12059                 VectorSubtract(loc->maxs, loc->mins, size);
12060         }
12061
12062         for (i = 0;i < 6*4*3;)
12063                 for (j = 0;j < 3;j++, i++)
12064                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
12065
12066         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
12067         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12068         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
12069 }
12070
12071 void R_DrawLocs(void)
12072 {
12073         int index;
12074         cl_locnode_t *loc, *nearestloc;
12075         vec3_t center;
12076         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
12077         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
12078         {
12079                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
12080                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
12081         }
12082 }
12083
12084 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
12085 {
12086         if (decalsystem->decals)
12087                 Mem_Free(decalsystem->decals);
12088         memset(decalsystem, 0, sizeof(*decalsystem));
12089 }
12090
12091 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)
12092 {
12093         tridecal_t *decal;
12094         tridecal_t *decals;
12095         int i;
12096
12097         // expand or initialize the system
12098         if (decalsystem->maxdecals <= decalsystem->numdecals)
12099         {
12100                 decalsystem_t old = *decalsystem;
12101                 qboolean useshortelements;
12102                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
12103                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
12104                 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)));
12105                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
12106                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
12107                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
12108                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
12109                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
12110                 if (decalsystem->numdecals)
12111                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
12112                 if (old.decals)
12113                         Mem_Free(old.decals);
12114                 for (i = 0;i < decalsystem->maxdecals*3;i++)
12115                         decalsystem->element3i[i] = i;
12116                 if (useshortelements)
12117                         for (i = 0;i < decalsystem->maxdecals*3;i++)
12118                                 decalsystem->element3s[i] = i;
12119         }
12120
12121         // grab a decal and search for another free slot for the next one
12122         decals = decalsystem->decals;
12123         decal = decalsystem->decals + (i = decalsystem->freedecal++);
12124         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
12125                 ;
12126         decalsystem->freedecal = i;
12127         if (decalsystem->numdecals <= i)
12128                 decalsystem->numdecals = i + 1;
12129
12130         // initialize the decal
12131         decal->lived = 0;
12132         decal->triangleindex = triangleindex;
12133         decal->surfaceindex = surfaceindex;
12134         decal->decalsequence = decalsequence;
12135         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
12136         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
12137         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
12138         decal->color4ub[0][3] = 255;
12139         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
12140         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
12141         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
12142         decal->color4ub[1][3] = 255;
12143         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
12144         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
12145         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
12146         decal->color4ub[2][3] = 255;
12147         decal->vertex3f[0][0] = v0[0];
12148         decal->vertex3f[0][1] = v0[1];
12149         decal->vertex3f[0][2] = v0[2];
12150         decal->vertex3f[1][0] = v1[0];
12151         decal->vertex3f[1][1] = v1[1];
12152         decal->vertex3f[1][2] = v1[2];
12153         decal->vertex3f[2][0] = v2[0];
12154         decal->vertex3f[2][1] = v2[1];
12155         decal->vertex3f[2][2] = v2[2];
12156         decal->texcoord2f[0][0] = t0[0];
12157         decal->texcoord2f[0][1] = t0[1];
12158         decal->texcoord2f[1][0] = t1[0];
12159         decal->texcoord2f[1][1] = t1[1];
12160         decal->texcoord2f[2][0] = t2[0];
12161         decal->texcoord2f[2][1] = t2[1];
12162 }
12163
12164 extern cvar_t cl_decals_bias;
12165 extern cvar_t cl_decals_models;
12166 extern cvar_t cl_decals_newsystem_intensitymultiplier;
12167 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)
12168 {
12169         matrix4x4_t projection;
12170         decalsystem_t *decalsystem;
12171         qboolean dynamic;
12172         dp_model_t *model;
12173         const float *vertex3f;
12174         const msurface_t *surface;
12175         const msurface_t *surfaces;
12176         const int *surfacelist;
12177         const texture_t *texture;
12178         int numtriangles;
12179         int numsurfacelist;
12180         int surfacelistindex;
12181         int surfaceindex;
12182         int triangleindex;
12183         int cornerindex;
12184         int index;
12185         int numpoints;
12186         const int *e;
12187         float localorigin[3];
12188         float localnormal[3];
12189         float localmins[3];
12190         float localmaxs[3];
12191         float localsize;
12192         float v[9][3];
12193         float tc[9][2];
12194         float c[9][4];
12195         //float normal[3];
12196         float planes[6][4];
12197         float f;
12198         float points[2][9][3];
12199         float angles[3];
12200         float temp[3];
12201
12202         decalsystem = &ent->decalsystem;
12203         model = ent->model;
12204         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
12205         {
12206                 R_DecalSystem_Reset(&ent->decalsystem);
12207                 return;
12208         }
12209
12210         if (!model->brush.data_nodes && !cl_decals_models.integer)
12211         {
12212                 if (decalsystem->model)
12213                         R_DecalSystem_Reset(decalsystem);
12214                 return;
12215         }
12216
12217         if (decalsystem->model != model)
12218                 R_DecalSystem_Reset(decalsystem);
12219         decalsystem->model = model;
12220
12221         RSurf_ActiveModelEntity(ent, false, false, false);
12222
12223         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
12224         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
12225         VectorNormalize(localnormal);
12226         localsize = worldsize*rsurface.inversematrixscale;
12227         localmins[0] = localorigin[0] - localsize;
12228         localmins[1] = localorigin[1] - localsize;
12229         localmins[2] = localorigin[2] - localsize;
12230         localmaxs[0] = localorigin[0] + localsize;
12231         localmaxs[1] = localorigin[1] + localsize;
12232         localmaxs[2] = localorigin[2] + localsize;
12233
12234         //VectorCopy(localnormal, planes[4]);
12235         //VectorVectors(planes[4], planes[2], planes[0]);
12236         AnglesFromVectors(angles, localnormal, NULL, false);
12237         AngleVectors(angles, planes[0], planes[2], planes[4]);
12238         VectorNegate(planes[0], planes[1]);
12239         VectorNegate(planes[2], planes[3]);
12240         VectorNegate(planes[4], planes[5]);
12241         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
12242         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
12243         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
12244         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
12245         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
12246         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
12247
12248 #if 1
12249 // works
12250 {
12251         matrix4x4_t forwardprojection;
12252         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
12253         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
12254 }
12255 #else
12256 // broken
12257 {
12258         float projectionvector[4][3];
12259         VectorScale(planes[0], ilocalsize, projectionvector[0]);
12260         VectorScale(planes[2], ilocalsize, projectionvector[1]);
12261         VectorScale(planes[4], ilocalsize, projectionvector[2]);
12262         projectionvector[0][0] = planes[0][0] * ilocalsize;
12263         projectionvector[0][1] = planes[1][0] * ilocalsize;
12264         projectionvector[0][2] = planes[2][0] * ilocalsize;
12265         projectionvector[1][0] = planes[0][1] * ilocalsize;
12266         projectionvector[1][1] = planes[1][1] * ilocalsize;
12267         projectionvector[1][2] = planes[2][1] * ilocalsize;
12268         projectionvector[2][0] = planes[0][2] * ilocalsize;
12269         projectionvector[2][1] = planes[1][2] * ilocalsize;
12270         projectionvector[2][2] = planes[2][2] * ilocalsize;
12271         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
12272         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
12273         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
12274         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
12275 }
12276 #endif
12277
12278         dynamic = model->surfmesh.isanimated;
12279         vertex3f = rsurface.modelvertex3f;
12280         numsurfacelist = model->nummodelsurfaces;
12281         surfacelist = model->sortedmodelsurfaces;
12282         surfaces = model->data_surfaces;
12283         for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
12284         {
12285                 surfaceindex = surfacelist[surfacelistindex];
12286                 surface = surfaces + surfaceindex;
12287                 // check cull box first because it rejects more than any other check
12288                 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
12289                         continue;
12290                 // skip transparent surfaces
12291                 texture = surface->texture;
12292                 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12293                         continue;
12294                 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12295                         continue;
12296                 numtriangles = surface->num_triangles;
12297                 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
12298                 {
12299                         for (cornerindex = 0;cornerindex < 3;cornerindex++)
12300                         {
12301                                 index = 3*e[cornerindex];
12302                                 VectorCopy(vertex3f + index, v[cornerindex]);
12303                         }
12304                         // cull backfaces
12305                         //TriangleNormal(v[0], v[1], v[2], normal);
12306                         //if (DotProduct(normal, localnormal) < 0.0f)
12307                         //      continue;
12308                         // clip by each of the box planes formed from the projection matrix
12309                         // if anything survives, we emit the decal
12310                         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]);
12311                         if (numpoints < 3)
12312                                 continue;
12313                         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]);
12314                         if (numpoints < 3)
12315                                 continue;
12316                         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]);
12317                         if (numpoints < 3)
12318                                 continue;
12319                         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]);
12320                         if (numpoints < 3)
12321                                 continue;
12322                         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]);
12323                         if (numpoints < 3)
12324                                 continue;
12325                         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]);
12326                         if (numpoints < 3)
12327                                 continue;
12328                         // some part of the triangle survived, so we have to accept it...
12329                         if (dynamic)
12330                         {
12331                                 // dynamic always uses the original triangle
12332                                 numpoints = 3;
12333                                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
12334                                 {
12335                                         index = 3*e[cornerindex];
12336                                         VectorCopy(vertex3f + index, v[cornerindex]);
12337                                 }
12338                         }
12339                         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
12340                         {
12341                                 // convert vertex positions to texcoords
12342                                 Matrix4x4_Transform(&projection, v[cornerindex], temp);
12343                                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
12344                                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
12345                                 // calculate distance fade from the projection origin
12346                                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
12347                                 f = bound(0.0f, f, 1.0f);
12348                                 c[cornerindex][0] = r * f;
12349                                 c[cornerindex][1] = g * f;
12350                                 c[cornerindex][2] = b * f;
12351                                 c[cornerindex][3] = 1.0f;
12352                                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
12353                         }
12354                         if (dynamic)
12355                                 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);
12356                         else
12357                                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
12358                                         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);
12359                 }
12360         }
12361 }
12362
12363 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
12364 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)
12365 {
12366         int renderentityindex;
12367         float worldmins[3];
12368         float worldmaxs[3];
12369         entity_render_t *ent;
12370
12371         if (!cl_decals_newsystem.integer)
12372                 return;
12373
12374         worldmins[0] = worldorigin[0] - worldsize;
12375         worldmins[1] = worldorigin[1] - worldsize;
12376         worldmins[2] = worldorigin[2] - worldsize;
12377         worldmaxs[0] = worldorigin[0] + worldsize;
12378         worldmaxs[1] = worldorigin[1] + worldsize;
12379         worldmaxs[2] = worldorigin[2] + worldsize;
12380
12381         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12382
12383         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
12384         {
12385                 ent = r_refdef.scene.entities[renderentityindex];
12386                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
12387                         continue;
12388
12389                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12390         }
12391 }
12392
12393 typedef struct r_decalsystem_splatqueue_s
12394 {
12395         vec3_t worldorigin;
12396         vec3_t worldnormal;
12397         float color[4];
12398         float tcrange[4];
12399         float worldsize;
12400         int decalsequence;
12401 }
12402 r_decalsystem_splatqueue_t;
12403
12404 int r_decalsystem_numqueued = 0;
12405 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12406
12407 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)
12408 {
12409         r_decalsystem_splatqueue_t *queue;
12410
12411         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12412                 return;
12413
12414         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12415         VectorCopy(worldorigin, queue->worldorigin);
12416         VectorCopy(worldnormal, queue->worldnormal);
12417         Vector4Set(queue->color, r, g, b, a);
12418         Vector4Set(queue->tcrange, s1, t1, s2, t2);
12419         queue->worldsize = worldsize;
12420         queue->decalsequence = cl.decalsequence++;
12421 }
12422
12423 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12424 {
12425         int i;
12426         r_decalsystem_splatqueue_t *queue;
12427
12428         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12429                 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);
12430         r_decalsystem_numqueued = 0;
12431 }
12432
12433 extern cvar_t cl_decals_max;
12434 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12435 {
12436         int i;
12437         decalsystem_t *decalsystem = &ent->decalsystem;
12438         int numdecals;
12439         int killsequence;
12440         tridecal_t *decal;
12441         float frametime;
12442         float lifetime;
12443
12444         if (!decalsystem->numdecals)
12445                 return;
12446
12447         if (r_showsurfaces.integer)
12448                 return;
12449
12450         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12451         {
12452                 R_DecalSystem_Reset(decalsystem);
12453                 return;
12454         }
12455
12456         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
12457         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12458
12459         if (decalsystem->lastupdatetime)
12460                 frametime = (cl.time - decalsystem->lastupdatetime);
12461         else
12462                 frametime = 0;
12463         decalsystem->lastupdatetime = cl.time;
12464         decal = decalsystem->decals;
12465         numdecals = decalsystem->numdecals;
12466
12467         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12468         {
12469                 if (decal->color4ub[0][3])
12470                 {
12471                         decal->lived += frametime;
12472                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
12473                         {
12474                                 memset(decal, 0, sizeof(*decal));
12475                                 if (decalsystem->freedecal > i)
12476                                         decalsystem->freedecal = i;
12477                         }
12478                 }
12479         }
12480         decal = decalsystem->decals;
12481         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
12482                 numdecals--;
12483
12484         // collapse the array by shuffling the tail decals into the gaps
12485         for (;;)
12486         {
12487                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
12488                         decalsystem->freedecal++;
12489                 if (decalsystem->freedecal == numdecals)
12490                         break;
12491                 decal[decalsystem->freedecal] = decal[--numdecals];
12492         }
12493
12494         decalsystem->numdecals = numdecals;
12495
12496         if (numdecals <= 0)
12497         {
12498                 // if there are no decals left, reset decalsystem
12499                 R_DecalSystem_Reset(decalsystem);
12500         }
12501 }
12502
12503 extern skinframe_t *decalskinframe;
12504 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12505 {
12506         int i;
12507         decalsystem_t *decalsystem = &ent->decalsystem;
12508         int numdecals;
12509         tridecal_t *decal;
12510         float faderate;
12511         float alpha;
12512         float *v3f;
12513         float *c4f;
12514         float *t2f;
12515         const int *e;
12516         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12517         int numtris = 0;
12518
12519         numdecals = decalsystem->numdecals;
12520         if (!numdecals)
12521                 return;
12522
12523         if (r_showsurfaces.integer)
12524                 return;
12525
12526         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12527         {
12528                 R_DecalSystem_Reset(decalsystem);
12529                 return;
12530         }
12531
12532         // if the model is static it doesn't matter what value we give for
12533         // wantnormals and wanttangents, so this logic uses only rules applicable
12534         // to a model, knowing that they are meaningless otherwise
12535         if (ent == r_refdef.scene.worldentity)
12536                 RSurf_ActiveWorldEntity();
12537         else
12538                 RSurf_ActiveModelEntity(ent, false, false, false);
12539
12540         decalsystem->lastupdatetime = cl.time;
12541         decal = decalsystem->decals;
12542
12543         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12544
12545         // update vertex positions for animated models
12546         v3f = decalsystem->vertex3f;
12547         c4f = decalsystem->color4f;
12548         t2f = decalsystem->texcoord2f;
12549         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12550         {
12551                 if (!decal->color4ub[0][3])
12552                         continue;
12553
12554                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12555                         continue;
12556
12557                 // update color values for fading decals
12558                 if (decal->lived >= cl_decals_time.value)
12559                 {
12560                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12561                         alpha *= (1.0f/255.0f);
12562                 }
12563                 else
12564                         alpha = 1.0f/255.0f;
12565
12566                 c4f[ 0] = decal->color4ub[0][0] * alpha;
12567                 c4f[ 1] = decal->color4ub[0][1] * alpha;
12568                 c4f[ 2] = decal->color4ub[0][2] * alpha;
12569                 c4f[ 3] = 1;
12570                 c4f[ 4] = decal->color4ub[1][0] * alpha;
12571                 c4f[ 5] = decal->color4ub[1][1] * alpha;
12572                 c4f[ 6] = decal->color4ub[1][2] * alpha;
12573                 c4f[ 7] = 1;
12574                 c4f[ 8] = decal->color4ub[2][0] * alpha;
12575                 c4f[ 9] = decal->color4ub[2][1] * alpha;
12576                 c4f[10] = decal->color4ub[2][2] * alpha;
12577                 c4f[11] = 1;
12578
12579                 t2f[0] = decal->texcoord2f[0][0];
12580                 t2f[1] = decal->texcoord2f[0][1];
12581                 t2f[2] = decal->texcoord2f[1][0];
12582                 t2f[3] = decal->texcoord2f[1][1];
12583                 t2f[4] = decal->texcoord2f[2][0];
12584                 t2f[5] = decal->texcoord2f[2][1];
12585
12586                 // update vertex positions for animated models
12587                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12588                 {
12589                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12590                         VectorCopy(rsurface.modelvertexposition[e[0]].vertex3f, v3f);
12591                         VectorCopy(rsurface.modelvertexposition[e[1]].vertex3f, v3f + 3);
12592                         VectorCopy(rsurface.modelvertexposition[e[2]].vertex3f, v3f + 6);
12593                 }
12594                 else
12595                 {
12596                         VectorCopy(decal->vertex3f[0], v3f);
12597                         VectorCopy(decal->vertex3f[1], v3f + 3);
12598                         VectorCopy(decal->vertex3f[2], v3f + 6);
12599                 }
12600
12601                 if (r_refdef.fogenabled)
12602                 {
12603                         alpha = RSurf_FogVertex(v3f);
12604                         VectorScale(c4f, alpha, c4f);
12605                         alpha = RSurf_FogVertex(v3f + 3);
12606                         VectorScale(c4f + 4, alpha, c4f + 4);
12607                         alpha = RSurf_FogVertex(v3f + 6);
12608                         VectorScale(c4f + 8, alpha, c4f + 8);
12609                 }
12610
12611                 v3f += 9;
12612                 c4f += 12;
12613                 t2f += 6;
12614                 numtris++;
12615         }
12616
12617         if (numtris > 0)
12618         {
12619                 r_refdef.stats.drawndecals += numtris;
12620
12621                 // now render the decals all at once
12622                 // (this assumes they all use one particle font texture!)
12623                 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);
12624                 R_Mesh_ResetTextureState();
12625                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12626                 GL_DepthMask(false);
12627                 GL_DepthRange(0, 1);
12628                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12629                 GL_DepthTest(true);
12630                 GL_CullFace(GL_NONE);
12631                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12632                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
12633                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12634         }
12635 }
12636
12637 static void R_DrawModelDecals(void)
12638 {
12639         int i, numdecals;
12640
12641         // fade faster when there are too many decals
12642         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12643         for (i = 0;i < r_refdef.scene.numentities;i++)
12644                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12645
12646         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12647         for (i = 0;i < r_refdef.scene.numentities;i++)
12648                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12649                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12650
12651         R_DecalSystem_ApplySplatEntitiesQueue();
12652
12653         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12654         for (i = 0;i < r_refdef.scene.numentities;i++)
12655                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12656
12657         r_refdef.stats.totaldecals += numdecals;
12658
12659         if (r_showsurfaces.integer)
12660                 return;
12661
12662         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12663
12664         for (i = 0;i < r_refdef.scene.numentities;i++)
12665         {
12666                 if (!r_refdef.viewcache.entityvisible[i])
12667                         continue;
12668                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12669                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12670         }
12671 }
12672
12673 extern cvar_t mod_collision_bih;
12674 void R_DrawDebugModel(void)
12675 {
12676         entity_render_t *ent = rsurface.entity;
12677         int i, j, k, l, flagsmask;
12678         const msurface_t *surface;
12679         dp_model_t *model = ent->model;
12680         vec3_t v;
12681
12682         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12683
12684         R_Mesh_ResetTextureState();
12685         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12686         GL_DepthRange(0, 1);
12687         GL_DepthTest(!r_showdisabledepthtest.integer);
12688         GL_DepthMask(false);
12689         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12690
12691         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12692         {
12693                 int triangleindex;
12694                 int bihleafindex;
12695                 qboolean cullbox = ent == r_refdef.scene.worldentity;
12696                 const q3mbrush_t *brush;
12697                 const bih_t *bih = &model->collision_bih;
12698                 const bih_leaf_t *bihleaf;
12699                 float vertex3f[3][3];
12700                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12701                 cullbox = false;
12702                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12703                 {
12704                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12705                                 continue;
12706                         switch (bihleaf->type)
12707                         {
12708                         case BIH_BRUSH:
12709                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12710                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12711                                 {
12712                                         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);
12713                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12714                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12715                                 }
12716                                 break;
12717                         case BIH_COLLISIONTRIANGLE:
12718                                 triangleindex = bihleaf->itemindex;
12719                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12720                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12721                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12722                                 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);
12723                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12724                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12725                                 break;
12726                         case BIH_RENDERTRIANGLE:
12727                                 triangleindex = bihleaf->itemindex;
12728                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12729                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12730                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12731                                 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);
12732                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12733                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12734                                 break;
12735                         }
12736                 }
12737         }
12738
12739         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12740
12741         if (r_showtris.integer || r_shownormals.integer)
12742         {
12743                 if (r_showdisabledepthtest.integer)
12744                 {
12745                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12746                         GL_DepthMask(false);
12747                 }
12748                 else
12749                 {
12750                         GL_BlendFunc(GL_ONE, GL_ZERO);
12751                         GL_DepthMask(true);
12752                 }
12753                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12754                 {
12755                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12756                                 continue;
12757                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12758                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12759                         {
12760                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12761                                 if (r_showtris.value > 0)
12762                                 {
12763                                         if (!rsurface.texture->currentlayers->depthmask)
12764                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12765                                         else if (ent == r_refdef.scene.worldentity)
12766                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12767                                         else
12768                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12769                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12770                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
12771                                         RSurf_DrawBatch();
12772                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
12773                                         CHECKGLERROR
12774                                 }
12775                                 if (r_shownormals.value < 0)
12776                                 {
12777                                         qglBegin(GL_LINES);
12778                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12779                                         {
12780                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12781                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12782                                                 qglVertex3f(v[0], v[1], v[2]);
12783                                                 VectorMA(v, -r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12784                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12785                                                 qglVertex3f(v[0], v[1], v[2]);
12786                                         }
12787                                         qglEnd();
12788                                         CHECKGLERROR
12789                                 }
12790                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12791                                 {
12792                                         qglBegin(GL_LINES);
12793                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12794                                         {
12795                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12796                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12797                                                 qglVertex3f(v[0], v[1], v[2]);
12798                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12799                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12800                                                 qglVertex3f(v[0], v[1], v[2]);
12801                                         }
12802                                         qglEnd();
12803                                         CHECKGLERROR
12804                                         qglBegin(GL_LINES);
12805                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12806                                         {
12807                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12808                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12809                                                 qglVertex3f(v[0], v[1], v[2]);
12810                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12811                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12812                                                 qglVertex3f(v[0], v[1], v[2]);
12813                                         }
12814                                         qglEnd();
12815                                         CHECKGLERROR
12816                                         qglBegin(GL_LINES);
12817                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12818                                         {
12819                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12820                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12821                                                 qglVertex3f(v[0], v[1], v[2]);
12822                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12823                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12824                                                 qglVertex3f(v[0], v[1], v[2]);
12825                                         }
12826                                         qglEnd();
12827                                         CHECKGLERROR
12828                                 }
12829                         }
12830                 }
12831                 rsurface.texture = NULL;
12832         }
12833 }
12834
12835 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
12836 int r_maxsurfacelist = 0;
12837 const msurface_t **r_surfacelist = NULL;
12838 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12839 {
12840         int i, j, endj, flagsmask;
12841         dp_model_t *model = r_refdef.scene.worldmodel;
12842         msurface_t *surfaces;
12843         unsigned char *update;
12844         int numsurfacelist = 0;
12845         if (model == NULL)
12846                 return;
12847
12848         if (r_maxsurfacelist < model->num_surfaces)
12849         {
12850                 r_maxsurfacelist = model->num_surfaces;
12851                 if (r_surfacelist)
12852                         Mem_Free((msurface_t**)r_surfacelist);
12853                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12854         }
12855
12856         RSurf_ActiveWorldEntity();
12857
12858         surfaces = model->data_surfaces;
12859         update = model->brushq1.lightmapupdateflags;
12860
12861         // update light styles on this submodel
12862         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12863         {
12864                 model_brush_lightstyleinfo_t *style;
12865                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12866                 {
12867                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12868                         {
12869                                 int *list = style->surfacelist;
12870                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12871                                 for (j = 0;j < style->numsurfaces;j++)
12872                                         update[list[j]] = true;
12873                         }
12874                 }
12875         }
12876
12877         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12878
12879         if (debug)
12880         {
12881                 R_DrawDebugModel();
12882                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12883                 return;
12884         }
12885
12886         rsurface.lightmaptexture = NULL;
12887         rsurface.deluxemaptexture = NULL;
12888         rsurface.uselightmaptexture = false;
12889         rsurface.texture = NULL;
12890         rsurface.rtlight = NULL;
12891         numsurfacelist = 0;
12892         // add visible surfaces to draw list
12893         for (i = 0;i < model->nummodelsurfaces;i++)
12894         {
12895                 j = model->sortedmodelsurfaces[i];
12896                 if (r_refdef.viewcache.world_surfacevisible[j])
12897                         r_surfacelist[numsurfacelist++] = surfaces + j;
12898         }
12899         // update lightmaps if needed
12900         if (model->brushq1.firstrender)
12901         {
12902                 model->brushq1.firstrender = false;
12903                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12904                         if (update[j])
12905                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12906         }
12907         else if (update)
12908         {
12909                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12910                         if (r_refdef.viewcache.world_surfacevisible[j])
12911                                 if (update[j])
12912                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12913         }
12914         // don't do anything if there were no surfaces
12915         if (!numsurfacelist)
12916         {
12917                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12918                 return;
12919         }
12920         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12921         GL_AlphaTest(false);
12922
12923         // add to stats if desired
12924         if (r_speeds.integer && !skysurfaces && !depthonly)
12925         {
12926                 r_refdef.stats.world_surfaces += numsurfacelist;
12927                 for (j = 0;j < numsurfacelist;j++)
12928                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
12929         }
12930
12931         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12932 }
12933
12934 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12935 {
12936         int i, j, endj, flagsmask;
12937         dp_model_t *model = ent->model;
12938         msurface_t *surfaces;
12939         unsigned char *update;
12940         int numsurfacelist = 0;
12941         if (model == NULL)
12942                 return;
12943
12944         if (r_maxsurfacelist < model->num_surfaces)
12945         {
12946                 r_maxsurfacelist = model->num_surfaces;
12947                 if (r_surfacelist)
12948                         Mem_Free((msurface_t **)r_surfacelist);
12949                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12950         }
12951
12952         // if the model is static it doesn't matter what value we give for
12953         // wantnormals and wanttangents, so this logic uses only rules applicable
12954         // to a model, knowing that they are meaningless otherwise
12955         if (ent == r_refdef.scene.worldentity)
12956                 RSurf_ActiveWorldEntity();
12957         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12958                 RSurf_ActiveModelEntity(ent, false, false, false);
12959         else if (prepass)
12960                 RSurf_ActiveModelEntity(ent, true, true, true);
12961         else if (depthonly)
12962         {
12963                 switch (vid.renderpath)
12964                 {
12965                 case RENDERPATH_GL20:
12966                 case RENDERPATH_CGGL:
12967                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12968                         break;
12969                 case RENDERPATH_GL13:
12970                 case RENDERPATH_GL11:
12971                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12972                         break;
12973                 }
12974         }
12975         else
12976         {
12977                 switch (vid.renderpath)
12978                 {
12979                 case RENDERPATH_GL20:
12980                 case RENDERPATH_CGGL:
12981                         RSurf_ActiveModelEntity(ent, true, true, false);
12982                         break;
12983                 case RENDERPATH_GL13:
12984                 case RENDERPATH_GL11:
12985                         RSurf_ActiveModelEntity(ent, true, false, false);
12986                         break;
12987                 }
12988         }
12989
12990         surfaces = model->data_surfaces;
12991         update = model->brushq1.lightmapupdateflags;
12992
12993         // update light styles
12994         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12995         {
12996                 model_brush_lightstyleinfo_t *style;
12997                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12998                 {
12999                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
13000                         {
13001                                 int *list = style->surfacelist;
13002                                 style->value = r_refdef.scene.lightstylevalue[style->style];
13003                                 for (j = 0;j < style->numsurfaces;j++)
13004                                         update[list[j]] = true;
13005                         }
13006                 }
13007         }
13008
13009         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13010
13011         if (debug)
13012         {
13013                 R_DrawDebugModel();
13014                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13015                 return;
13016         }
13017
13018         rsurface.lightmaptexture = NULL;
13019         rsurface.deluxemaptexture = NULL;
13020         rsurface.uselightmaptexture = false;
13021         rsurface.texture = NULL;
13022         rsurface.rtlight = NULL;
13023         numsurfacelist = 0;
13024         // add visible surfaces to draw list
13025         for (i = 0;i < model->nummodelsurfaces;i++)
13026                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
13027         // don't do anything if there were no surfaces
13028         if (!numsurfacelist)
13029         {
13030                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13031                 return;
13032         }
13033         // update lightmaps if needed
13034         if (update)
13035         {
13036                 int updated = 0;
13037                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13038                 {
13039                         if (update[j])
13040                         {
13041                                 updated++;
13042                                 R_BuildLightMap(ent, surfaces + j);
13043                         }
13044                 }
13045         }
13046         if (update)
13047                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13048                         if (update[j])
13049                                 R_BuildLightMap(ent, surfaces + j);
13050         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13051         GL_AlphaTest(false);
13052
13053         // add to stats if desired
13054         if (r_speeds.integer && !skysurfaces && !depthonly)
13055         {
13056                 r_refdef.stats.entities_surfaces += numsurfacelist;
13057                 for (j = 0;j < numsurfacelist;j++)
13058                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
13059         }
13060
13061         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13062 }
13063
13064 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
13065 {
13066         static texture_t texture;
13067         static msurface_t surface;
13068         const msurface_t *surfacelist = &surface;
13069
13070         // fake enough texture and surface state to render this geometry
13071
13072         texture.update_lastrenderframe = -1; // regenerate this texture
13073         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
13074         texture.currentskinframe = skinframe;
13075         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
13076         texture.offsetmapping = OFFSETMAPPING_OFF;
13077         texture.offsetscale = 1;
13078         texture.specularscalemod = 1;
13079         texture.specularpowermod = 1;
13080
13081         surface.texture = &texture;
13082         surface.num_triangles = numtriangles;
13083         surface.num_firsttriangle = firsttriangle;
13084         surface.num_vertices = numvertices;
13085         surface.num_firstvertex = firstvertex;
13086
13087         // now render it
13088         rsurface.texture = R_GetCurrentTexture(surface.texture);
13089         rsurface.lightmaptexture = NULL;
13090         rsurface.deluxemaptexture = NULL;
13091         rsurface.uselightmaptexture = false;
13092         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
13093 }
13094
13095 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)
13096 {
13097         static msurface_t surface;
13098         const msurface_t *surfacelist = &surface;
13099
13100         // fake enough texture and surface state to render this geometry
13101
13102         surface.texture = texture;
13103         surface.num_triangles = numtriangles;
13104         surface.num_firsttriangle = firsttriangle;
13105         surface.num_vertices = numvertices;
13106         surface.num_firstvertex = firstvertex;
13107
13108         // now render it
13109         rsurface.texture = R_GetCurrentTexture(surface.texture);
13110         rsurface.lightmaptexture = NULL;
13111         rsurface.deluxemaptexture = NULL;
13112         rsurface.uselightmaptexture = false;
13113         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
13114 }