]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
fix a crash on deformvertexes wave
[xonotic/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
140 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)"};
141 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
142 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"};
143 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
144 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
145
146 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
147 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
148 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
149 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
150
151 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
152 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
153 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
154 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
155 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
156 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
157 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
158
159 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
160 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
161 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
162 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)"};
163
164 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"};
165
166 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"};
167
168 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
169
170 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
171 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
172 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
173 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
174 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
175 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
176 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "16", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
177
178 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
179
180 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "1", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
181
182 extern cvar_t v_glslgamma;
183
184 extern qboolean v_flipped_state;
185
186 static struct r_bloomstate_s
187 {
188         qboolean enabled;
189         qboolean hdr;
190
191         int bloomwidth, bloomheight;
192
193         int screentexturewidth, screentextureheight;
194         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
195
196         int bloomtexturewidth, bloomtextureheight;
197         rtexture_t *texture_bloom;
198
199         // arrays for rendering the screen passes
200         float screentexcoord2f[8];
201         float bloomtexcoord2f[8];
202         float offsettexcoord2f[8];
203
204         r_viewport_t viewport;
205 }
206 r_bloomstate;
207
208 r_waterstate_t r_waterstate;
209
210 /// shadow volume bsp struct with automatically growing nodes buffer
211 svbsp_t r_svbsp;
212
213 rtexture_t *r_texture_blanknormalmap;
214 rtexture_t *r_texture_white;
215 rtexture_t *r_texture_grey128;
216 rtexture_t *r_texture_black;
217 rtexture_t *r_texture_notexture;
218 rtexture_t *r_texture_whitecube;
219 rtexture_t *r_texture_normalizationcube;
220 rtexture_t *r_texture_fogattenuation;
221 rtexture_t *r_texture_fogheighttexture;
222 rtexture_t *r_texture_gammaramps;
223 unsigned int r_texture_gammaramps_serial;
224 //rtexture_t *r_texture_fogintensity;
225 rtexture_t *r_texture_reflectcube;
226
227 // TODO: hash lookups?
228 typedef struct cubemapinfo_s
229 {
230         char basename[64];
231         rtexture_t *texture;
232 }
233 cubemapinfo_t;
234
235 int r_texture_numcubemaps;
236 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
237
238 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
239 unsigned int r_numqueries;
240 unsigned int r_maxqueries;
241
242 typedef struct r_qwskincache_s
243 {
244         char name[MAX_QPATH];
245         skinframe_t *skinframe;
246 }
247 r_qwskincache_t;
248
249 static r_qwskincache_t *r_qwskincache;
250 static int r_qwskincache_size;
251
252 /// vertex coordinates for a quad that covers the screen exactly
253 const float r_screenvertex3f[12] =
254 {
255         0, 0, 0,
256         1, 0, 0,
257         1, 1, 0,
258         0, 1, 0
259 };
260
261 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
262 {
263         int i;
264         for (i = 0;i < verts;i++)
265         {
266                 out[0] = in[0] * r;
267                 out[1] = in[1] * g;
268                 out[2] = in[2] * b;
269                 out[3] = in[3];
270                 in += 4;
271                 out += 4;
272         }
273 }
274
275 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
276 {
277         int i;
278         for (i = 0;i < verts;i++)
279         {
280                 out[0] = r;
281                 out[1] = g;
282                 out[2] = b;
283                 out[3] = a;
284                 out += 4;
285         }
286 }
287
288 // FIXME: move this to client?
289 void FOG_clear(void)
290 {
291         if (gamemode == GAME_NEHAHRA)
292         {
293                 Cvar_Set("gl_fogenable", "0");
294                 Cvar_Set("gl_fogdensity", "0.2");
295                 Cvar_Set("gl_fogred", "0.3");
296                 Cvar_Set("gl_foggreen", "0.3");
297                 Cvar_Set("gl_fogblue", "0.3");
298         }
299         r_refdef.fog_density = 0;
300         r_refdef.fog_red = 0;
301         r_refdef.fog_green = 0;
302         r_refdef.fog_blue = 0;
303         r_refdef.fog_alpha = 1;
304         r_refdef.fog_start = 0;
305         r_refdef.fog_end = 16384;
306         r_refdef.fog_height = 1<<30;
307         r_refdef.fog_fadedepth = 128;
308         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
309 }
310
311 static void R_BuildBlankTextures(void)
312 {
313         unsigned char data[4];
314         data[2] = 128; // normal X
315         data[1] = 128; // normal Y
316         data[0] = 255; // normal Z
317         data[3] = 128; // height
318         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
319         data[0] = 255;
320         data[1] = 255;
321         data[2] = 255;
322         data[3] = 255;
323         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
324         data[0] = 128;
325         data[1] = 128;
326         data[2] = 128;
327         data[3] = 255;
328         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
329         data[0] = 0;
330         data[1] = 0;
331         data[2] = 0;
332         data[3] = 255;
333         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
334 }
335
336 static void R_BuildNoTexture(void)
337 {
338         int x, y;
339         unsigned char pix[16][16][4];
340         // this makes a light grey/dark grey checkerboard texture
341         for (y = 0;y < 16;y++)
342         {
343                 for (x = 0;x < 16;x++)
344                 {
345                         if ((y < 8) ^ (x < 8))
346                         {
347                                 pix[y][x][0] = 128;
348                                 pix[y][x][1] = 128;
349                                 pix[y][x][2] = 128;
350                                 pix[y][x][3] = 255;
351                         }
352                         else
353                         {
354                                 pix[y][x][0] = 64;
355                                 pix[y][x][1] = 64;
356                                 pix[y][x][2] = 64;
357                                 pix[y][x][3] = 255;
358                         }
359                 }
360         }
361         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
362 }
363
364 static void R_BuildWhiteCube(void)
365 {
366         unsigned char data[6*1*1*4];
367         memset(data, 255, sizeof(data));
368         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
369 }
370
371 static void R_BuildNormalizationCube(void)
372 {
373         int x, y, side;
374         vec3_t v;
375         vec_t s, t, intensity;
376 #define NORMSIZE 64
377         unsigned char *data;
378         data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
379         for (side = 0;side < 6;side++)
380         {
381                 for (y = 0;y < NORMSIZE;y++)
382                 {
383                         for (x = 0;x < NORMSIZE;x++)
384                         {
385                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
386                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
387                                 switch(side)
388                                 {
389                                 default:
390                                 case 0:
391                                         v[0] = 1;
392                                         v[1] = -t;
393                                         v[2] = -s;
394                                         break;
395                                 case 1:
396                                         v[0] = -1;
397                                         v[1] = -t;
398                                         v[2] = s;
399                                         break;
400                                 case 2:
401                                         v[0] = s;
402                                         v[1] = 1;
403                                         v[2] = t;
404                                         break;
405                                 case 3:
406                                         v[0] = s;
407                                         v[1] = -1;
408                                         v[2] = -t;
409                                         break;
410                                 case 4:
411                                         v[0] = s;
412                                         v[1] = -t;
413                                         v[2] = 1;
414                                         break;
415                                 case 5:
416                                         v[0] = -s;
417                                         v[1] = -t;
418                                         v[2] = -1;
419                                         break;
420                                 }
421                                 intensity = 127.0f / sqrt(DotProduct(v, v));
422                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
423                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
424                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
425                                 data[((side*64+y)*64+x)*4+3] = 255;
426                         }
427                 }
428         }
429         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
430         Mem_Free(data);
431 }
432
433 static void R_BuildFogTexture(void)
434 {
435         int x, b;
436 #define FOGWIDTH 256
437         unsigned char data1[FOGWIDTH][4];
438         //unsigned char data2[FOGWIDTH][4];
439         double d, r, alpha;
440
441         r_refdef.fogmasktable_start = r_refdef.fog_start;
442         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
443         r_refdef.fogmasktable_range = r_refdef.fogrange;
444         r_refdef.fogmasktable_density = r_refdef.fog_density;
445
446         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
447         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
448         {
449                 d = (x * r - r_refdef.fogmasktable_start);
450                 if(developer_extra.integer)
451                         Con_DPrintf("%f ", d);
452                 d = max(0, d);
453                 if (r_fog_exp2.integer)
454                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
455                 else
456                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
457                 if(developer_extra.integer)
458                         Con_DPrintf(" : %f ", alpha);
459                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
460                 if(developer_extra.integer)
461                         Con_DPrintf(" = %f\n", alpha);
462                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
463         }
464
465         for (x = 0;x < FOGWIDTH;x++)
466         {
467                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
468                 data1[x][0] = b;
469                 data1[x][1] = b;
470                 data1[x][2] = b;
471                 data1[x][3] = 255;
472                 //data2[x][0] = 255 - b;
473                 //data2[x][1] = 255 - b;
474                 //data2[x][2] = 255 - b;
475                 //data2[x][3] = 255;
476         }
477         if (r_texture_fogattenuation)
478         {
479                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
480                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
481         }
482         else
483         {
484                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, NULL);
485                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
486         }
487 }
488
489 static void R_BuildFogHeightTexture(void)
490 {
491         unsigned char *inpixels;
492         int size;
493         int x;
494         int y;
495         int j;
496         float c[4];
497         float f;
498         inpixels = NULL;
499         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
500         if (r_refdef.fogheighttexturename[0])
501                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false);
502         if (!inpixels)
503         {
504                 r_refdef.fog_height_tablesize = 0;
505                 if (r_texture_fogheighttexture)
506                         R_FreeTexture(r_texture_fogheighttexture);
507                 r_texture_fogheighttexture = NULL;
508                 if (r_refdef.fog_height_table2d)
509                         Mem_Free(r_refdef.fog_height_table2d);
510                 r_refdef.fog_height_table2d = NULL;
511                 if (r_refdef.fog_height_table1d)
512                         Mem_Free(r_refdef.fog_height_table1d);
513                 r_refdef.fog_height_table1d = NULL;
514                 return;
515         }
516         size = image_width;
517         r_refdef.fog_height_tablesize = size;
518         r_refdef.fog_height_table1d = Mem_Alloc(r_main_mempool, size * 4);
519         r_refdef.fog_height_table2d = Mem_Alloc(r_main_mempool, size * size * 4);
520         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
521         Mem_Free(inpixels);
522         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
523         // average fog color table accounting for every fog layer between a point
524         // and the camera.  (Note: attenuation is handled separately!)
525         for (y = 0;y < size;y++)
526         {
527                 for (x = 0;x < size;x++)
528                 {
529                         Vector4Clear(c);
530                         f = 0;
531                         if (x < y)
532                         {
533                                 for (j = x;j <= y;j++)
534                                 {
535                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
536                                         f++;
537                                 }
538                         }
539                         else
540                         {
541                                 for (j = x;j >= y;j--)
542                                 {
543                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
544                                         f++;
545                                 }
546                         }
547                         f = 1.0f / f;
548                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
549                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
550                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
551                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
552                 }
553         }
554         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, NULL);
555 }
556
557 //=======================================================================================================================================================
558
559 static const char *builtinshaderstring =
560 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
561 "// written by Forest 'LordHavoc' Hale\n"
562 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
563 "\n"
564 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
565 "# define USEFOG\n"
566 "#endif\n"
567 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
568 "#define USELIGHTMAP\n"
569 "#endif\n"
570 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
571 "#define USEEYEVECTOR\n"
572 "#endif\n"
573 "\n"
574 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
575 "# extension GL_ARB_texture_rectangle : enable\n"
576 "#endif\n"
577 "\n"
578 "#ifdef USESHADOWMAP2D\n"
579 "# ifdef GL_EXT_gpu_shader4\n"
580 "#   extension GL_EXT_gpu_shader4 : enable\n"
581 "# endif\n"
582 "# ifdef GL_ARB_texture_gather\n"
583 "#   extension GL_ARB_texture_gather : enable\n"
584 "# else\n"
585 "#   ifdef GL_AMD_texture_texture4\n"
586 "#     extension GL_AMD_texture_texture4 : enable\n"
587 "#   endif\n"
588 "# endif\n"
589 "#endif\n"
590 "\n"
591 "#ifdef USESHADOWMAPCUBE\n"
592 "# extension GL_EXT_gpu_shader4 : enable\n"
593 "#endif\n"
594 "\n"
595 "//#ifdef USESHADOWSAMPLER\n"
596 "//# extension GL_ARB_shadow : enable\n"
597 "//#endif\n"
598 "\n"
599 "//#ifdef __GLSL_CG_DATA_TYPES\n"
600 "//# define myhalf half\n"
601 "//# define myhalf2 half2\n"
602 "//# define myhalf3 half3\n"
603 "//# define myhalf4 half4\n"
604 "//#else\n"
605 "# define myhalf float\n"
606 "# define myhalf2 vec2\n"
607 "# define myhalf3 vec3\n"
608 "# define myhalf4 vec4\n"
609 "//#endif\n"
610 "\n"
611 "#ifdef VERTEX_SHADER\n"
612 "uniform mat4 ModelViewProjectionMatrix;\n"
613 "#endif\n"
614 "\n"
615 "#ifdef MODE_DEPTH_OR_SHADOW\n"
616 "#ifdef VERTEX_SHADER\n"
617 "void main(void)\n"
618 "{\n"
619 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
620 "}\n"
621 "#endif\n"
622 "#else // !MODE_DEPTH_ORSHADOW\n"
623 "\n"
624 "\n"
625 "\n"
626 "\n"
627 "#ifdef MODE_SHOWDEPTH\n"
628 "#ifdef VERTEX_SHADER\n"
629 "void main(void)\n"
630 "{\n"
631 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
632 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
633 "}\n"
634 "#endif\n"
635 "\n"
636 "#ifdef FRAGMENT_SHADER\n"
637 "void main(void)\n"
638 "{\n"
639 "       gl_FragColor = gl_Color;\n"
640 "}\n"
641 "#endif\n"
642 "#else // !MODE_SHOWDEPTH\n"
643 "\n"
644 "\n"
645 "\n"
646 "\n"
647 "#ifdef MODE_POSTPROCESS\n"
648 "varying vec2 TexCoord1;\n"
649 "varying vec2 TexCoord2;\n"
650 "\n"
651 "#ifdef VERTEX_SHADER\n"
652 "void main(void)\n"
653 "{\n"
654 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
655 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
656 "#ifdef USEBLOOM\n"
657 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
658 "#endif\n"
659 "}\n"
660 "#endif\n"
661 "\n"
662 "#ifdef FRAGMENT_SHADER\n"
663 "uniform sampler2D Texture_First;\n"
664 "#ifdef USEBLOOM\n"
665 "uniform sampler2D Texture_Second;\n"
666 "#endif\n"
667 "#ifdef USEGAMMARAMPS\n"
668 "uniform sampler2D Texture_GammaRamps;\n"
669 "#endif\n"
670 "#ifdef USESATURATION\n"
671 "uniform float Saturation;\n"
672 "#endif\n"
673 "#ifdef USEVIEWTINT\n"
674 "uniform vec4 ViewTintColor;\n"
675 "#endif\n"
676 "//uncomment these if you want to use them:\n"
677 "uniform vec4 UserVec1;\n"
678 "uniform vec4 UserVec2;\n"
679 "// uniform vec4 UserVec3;\n"
680 "// uniform vec4 UserVec4;\n"
681 "// uniform float ClientTime;\n"
682 "uniform vec2 PixelSize;\n"
683 "void main(void)\n"
684 "{\n"
685 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
686 "#ifdef USEBLOOM\n"
687 "       gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
688 "#endif\n"
689 "#ifdef USEVIEWTINT\n"
690 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
691 "#endif\n"
692 "\n"
693 "#ifdef USEPOSTPROCESSING\n"
694 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
695 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
696 "       float sobel = 1.0;\n"
697 "       // vec2 ts = textureSize(Texture_First, 0);\n"
698 "       // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
699 "       vec2 px = PixelSize;\n"
700 "       vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
701 "       vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,  0.0)).rgb;\n"
702 "       vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
703 "       vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
704 "       vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x,  0.0)).rgb;\n"
705 "       vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
706 "       vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
707 "       vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2(  0.0,-px.y)).rgb;\n"
708 "       vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
709 "       vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
710 "       vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2(  0.0, px.y)).rgb;\n"
711 "       vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
712 "       float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
713 "       float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
714 "       float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
715 "       float px4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
716 "       float px5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
717 "       float px6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
718 "       float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
719 "       float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
720 "       float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
721 "       float py4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
722 "       float py5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
723 "       float py6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
724 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
725 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
726 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
727 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
728 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
729 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
730 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
731 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
732 "#endif\n"
733 "\n"
734 "#ifdef USESATURATION\n"
735 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
736 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
737 "       //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
738 "       gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
739 "#endif\n"
740 "\n"
741 "#ifdef USEGAMMARAMPS\n"
742 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
743 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
744 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
745 "#endif\n"
746 "}\n"
747 "#endif\n"
748 "#else // !MODE_POSTPROCESS\n"
749 "\n"
750 "\n"
751 "\n"
752 "\n"
753 "#ifdef MODE_GENERIC\n"
754 "#ifdef USEDIFFUSE\n"
755 "varying vec2 TexCoord1;\n"
756 "#endif\n"
757 "#ifdef USESPECULAR\n"
758 "varying vec2 TexCoord2;\n"
759 "#endif\n"
760 "#ifdef VERTEX_SHADER\n"
761 "void main(void)\n"
762 "{\n"
763 "       gl_FrontColor = gl_Color;\n"
764 "#ifdef USEDIFFUSE\n"
765 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
766 "#endif\n"
767 "#ifdef USESPECULAR\n"
768 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
769 "#endif\n"
770 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
771 "}\n"
772 "#endif\n"
773 "\n"
774 "#ifdef FRAGMENT_SHADER\n"
775 "#ifdef USEDIFFUSE\n"
776 "uniform sampler2D Texture_First;\n"
777 "#endif\n"
778 "#ifdef USESPECULAR\n"
779 "uniform sampler2D Texture_Second;\n"
780 "#endif\n"
781 "\n"
782 "void main(void)\n"
783 "{\n"
784 "       gl_FragColor = gl_Color;\n"
785 "#ifdef USEDIFFUSE\n"
786 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
787 "#endif\n"
788 "\n"
789 "#ifdef USESPECULAR\n"
790 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
791 "# ifdef USECOLORMAPPING\n"
792 "       gl_FragColor *= tex2;\n"
793 "# endif\n"
794 "# ifdef USEGLOW\n"
795 "       gl_FragColor += tex2;\n"
796 "# endif\n"
797 "# ifdef USEVERTEXTEXTUREBLEND\n"
798 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
799 "# endif\n"
800 "#endif\n"
801 "}\n"
802 "#endif\n"
803 "#else // !MODE_GENERIC\n"
804 "\n"
805 "\n"
806 "\n"
807 "\n"
808 "#ifdef MODE_BLOOMBLUR\n"
809 "varying TexCoord;\n"
810 "#ifdef VERTEX_SHADER\n"
811 "void main(void)\n"
812 "{\n"
813 "       gl_FrontColor = gl_Color;\n"
814 "       TexCoord = gl_MultiTexCoord0.xy;\n"
815 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
816 "}\n"
817 "#endif\n"
818 "\n"
819 "#ifdef FRAGMENT_SHADER\n"
820 "uniform sampler2D Texture_First;\n"
821 "uniform vec4 BloomBlur_Parameters;\n"
822 "\n"
823 "void main(void)\n"
824 "{\n"
825 "       int i;\n"
826 "       vec2 tc = TexCoord;\n"
827 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
828 "       tc += BloomBlur_Parameters.xy;\n"
829 "       for (i = 1;i < SAMPLES;i++)\n"
830 "       {\n"
831 "               color += texture2D(Texture_First, tc).rgb;\n"
832 "               tc += BloomBlur_Parameters.xy;\n"
833 "       }\n"
834 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
835 "}\n"
836 "#endif\n"
837 "#else // !MODE_BLOOMBLUR\n"
838 "#ifdef MODE_REFRACTION\n"
839 "varying vec2 TexCoord;\n"
840 "varying vec4 ModelViewProjectionPosition;\n"
841 "uniform mat4 TexMatrix;\n"
842 "#ifdef VERTEX_SHADER\n"
843 "\n"
844 "void main(void)\n"
845 "{\n"
846 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
847 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
848 "       ModelViewProjectionPosition = gl_Position;\n"
849 "}\n"
850 "#endif\n"
851 "\n"
852 "#ifdef FRAGMENT_SHADER\n"
853 "uniform sampler2D Texture_Normal;\n"
854 "uniform sampler2D Texture_Refraction;\n"
855 "uniform sampler2D Texture_Reflection;\n"
856 "\n"
857 "uniform vec4 DistortScaleRefractReflect;\n"
858 "uniform vec4 ScreenScaleRefractReflect;\n"
859 "uniform vec4 ScreenCenterRefractReflect;\n"
860 "uniform vec4 RefractColor;\n"
861 "uniform vec4 ReflectColor;\n"
862 "uniform float ReflectFactor;\n"
863 "uniform float ReflectOffset;\n"
864 "\n"
865 "void main(void)\n"
866 "{\n"
867 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
868 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
869 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
870 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
871 "       // FIXME temporary hack to detect the case that the reflection\n"
872 "       // gets blackened at edges due to leaving the area that contains actual\n"
873 "       // content.\n"
874 "       // Remove this 'ack once we have a better way to stop this thing from\n"
875 "       // 'appening.\n"
876 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
877 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
878 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
879 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
880 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
881 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
882 "}\n"
883 "#endif\n"
884 "#else // !MODE_REFRACTION\n"
885 "\n"
886 "\n"
887 "\n"
888 "\n"
889 "#ifdef MODE_WATER\n"
890 "varying vec2 TexCoord;\n"
891 "varying vec3 EyeVector;\n"
892 "varying vec4 ModelViewProjectionPosition;\n"
893 "#ifdef VERTEX_SHADER\n"
894 "uniform vec3 EyePosition;\n"
895 "uniform mat4 TexMatrix;\n"
896 "\n"
897 "void main(void)\n"
898 "{\n"
899 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
900 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
901 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
902 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
903 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
904 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
905 "       ModelViewProjectionPosition = gl_Position;\n"
906 "}\n"
907 "#endif\n"
908 "\n"
909 "#ifdef FRAGMENT_SHADER\n"
910 "uniform sampler2D Texture_Normal;\n"
911 "uniform sampler2D Texture_Refraction;\n"
912 "uniform sampler2D Texture_Reflection;\n"
913 "\n"
914 "uniform vec4 DistortScaleRefractReflect;\n"
915 "uniform vec4 ScreenScaleRefractReflect;\n"
916 "uniform vec4 ScreenCenterRefractReflect;\n"
917 "uniform vec4 RefractColor;\n"
918 "uniform vec4 ReflectColor;\n"
919 "uniform float ReflectFactor;\n"
920 "uniform float ReflectOffset;\n"
921 "\n"
922 "void main(void)\n"
923 "{\n"
924 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
925 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
926 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
927 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
928 "       vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
929 "       // FIXME temporary hack to detect the case that the reflection\n"
930 "       // gets blackened at edges due to leaving the area that contains actual\n"
931 "       // content.\n"
932 "       // Remove this 'ack once we have a better way to stop this thing from\n"
933 "       // 'appening.\n"
934 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
935 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
936 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
937 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
938 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
939 "       f       = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
940 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
941 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
942 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
943 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
944 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
945 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
946 "}\n"
947 "#endif\n"
948 "#else // !MODE_WATER\n"
949 "\n"
950 "\n"
951 "\n"
952 "\n"
953 "// common definitions between vertex shader and fragment shader:\n"
954 "\n"
955 "varying vec2 TexCoord;\n"
956 "#ifdef USEVERTEXTEXTUREBLEND\n"
957 "varying vec2 TexCoord2;\n"
958 "#endif\n"
959 "#ifdef USELIGHTMAP\n"
960 "varying vec2 TexCoordLightmap;\n"
961 "#endif\n"
962 "\n"
963 "#ifdef MODE_LIGHTSOURCE\n"
964 "varying vec3 CubeVector;\n"
965 "#endif\n"
966 "\n"
967 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
968 "varying vec3 LightVector;\n"
969 "#endif\n"
970 "\n"
971 "#ifdef USEEYEVECTOR\n"
972 "varying vec3 EyeVector;\n"
973 "#endif\n"
974 "#ifdef USEFOG\n"
975 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
976 "#endif\n"
977 "\n"
978 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
979 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
980 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
981 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
982 "#endif\n"
983 "\n"
984 "#ifdef USEREFLECTION\n"
985 "varying vec4 ModelViewProjectionPosition;\n"
986 "#endif\n"
987 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
988 "uniform vec3 LightPosition;\n"
989 "varying vec4 ModelViewPosition;\n"
990 "#endif\n"
991 "\n"
992 "#ifdef MODE_LIGHTSOURCE\n"
993 "uniform vec3 LightPosition;\n"
994 "#endif\n"
995 "uniform vec3 EyePosition;\n"
996 "#ifdef MODE_LIGHTDIRECTION\n"
997 "uniform vec3 LightDir;\n"
998 "#endif\n"
999 "uniform vec4 FogPlane;\n"
1000 "\n"
1001 "#ifdef USESHADOWMAPORTHO\n"
1002 "varying vec3 ShadowMapTC;\n"
1003 "#endif\n"
1004 "\n"
1005 "\n"
1006 "\n"
1007 "\n"
1008 "\n"
1009 "// 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"
1010 "\n"
1011 "// fragment shader specific:\n"
1012 "#ifdef FRAGMENT_SHADER\n"
1013 "\n"
1014 "uniform sampler2D Texture_Normal;\n"
1015 "uniform sampler2D Texture_Color;\n"
1016 "uniform sampler2D Texture_Gloss;\n"
1017 "#ifdef USEGLOW\n"
1018 "uniform sampler2D Texture_Glow;\n"
1019 "#endif\n"
1020 "#ifdef USEVERTEXTEXTUREBLEND\n"
1021 "uniform sampler2D Texture_SecondaryNormal;\n"
1022 "uniform sampler2D Texture_SecondaryColor;\n"
1023 "uniform sampler2D Texture_SecondaryGloss;\n"
1024 "#ifdef USEGLOW\n"
1025 "uniform sampler2D Texture_SecondaryGlow;\n"
1026 "#endif\n"
1027 "#endif\n"
1028 "#ifdef USECOLORMAPPING\n"
1029 "uniform sampler2D Texture_Pants;\n"
1030 "uniform sampler2D Texture_Shirt;\n"
1031 "#endif\n"
1032 "#ifdef USEFOG\n"
1033 "#ifdef USEFOGHEIGHTTEXTURE\n"
1034 "uniform sampler2D Texture_FogHeightTexture;\n"
1035 "#endif\n"
1036 "uniform sampler2D Texture_FogMask;\n"
1037 "#endif\n"
1038 "#ifdef USELIGHTMAP\n"
1039 "uniform sampler2D Texture_Lightmap;\n"
1040 "#endif\n"
1041 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1042 "uniform sampler2D Texture_Deluxemap;\n"
1043 "#endif\n"
1044 "#ifdef USEREFLECTION\n"
1045 "uniform sampler2D Texture_Reflection;\n"
1046 "#endif\n"
1047 "\n"
1048 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1049 "uniform sampler2D Texture_ScreenDepth;\n"
1050 "uniform sampler2D Texture_ScreenNormalMap;\n"
1051 "#endif\n"
1052 "#ifdef USEDEFERREDLIGHTMAP\n"
1053 "uniform sampler2D Texture_ScreenDiffuse;\n"
1054 "uniform sampler2D Texture_ScreenSpecular;\n"
1055 "#endif\n"
1056 "\n"
1057 "uniform myhalf3 Color_Pants;\n"
1058 "uniform myhalf3 Color_Shirt;\n"
1059 "uniform myhalf3 FogColor;\n"
1060 "\n"
1061 "#ifdef USEFOG\n"
1062 "uniform float FogRangeRecip;\n"
1063 "uniform float FogPlaneViewDist;\n"
1064 "uniform float FogHeightFade;\n"
1065 "vec3 FogVertex(vec3 surfacecolor)\n"
1066 "{\n"
1067 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1068 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1069 "       float fogfrac;\n"
1070 "#ifdef USEFOGHEIGHTTEXTURE\n"
1071 "       vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1072 "       fogfrac = fogheightpixel.a;\n"
1073 "       return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1074 "#else\n"
1075 "# ifdef USEFOGOUTSIDE\n"
1076 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1077 "# else\n"
1078 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1079 "# endif\n"
1080 "       return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1081 "#endif\n"
1082 "}\n"
1083 "#endif\n"
1084 "\n"
1085 "#ifdef USEOFFSETMAPPING\n"
1086 "uniform float OffsetMapping_Scale;\n"
1087 "vec2 OffsetMapping(vec2 TexCoord)\n"
1088 "{\n"
1089 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1090 "       // 14 sample relief mapping: linear search and then binary search\n"
1091 "       // this basically steps forward a small amount repeatedly until it finds\n"
1092 "       // itself inside solid, then jitters forward and back using decreasing\n"
1093 "       // amounts to find the impact\n"
1094 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1095 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1096 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1097 "       vec3 RT = vec3(TexCoord, 1);\n"
1098 "       OffsetVector *= 0.1;\n"
1099 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1100 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1101 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\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)          - 0.5);\n"
1109 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1110 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1111 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1112 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1113 "       return RT.xy;\n"
1114 "#else\n"
1115 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1116 "       // this basically moves forward the full distance, and then backs up based\n"
1117 "       // on height of samples\n"
1118 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1119 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1120 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1121 "       TexCoord += OffsetVector;\n"
1122 "       OffsetVector *= 0.333;\n"
1123 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1124 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1125 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1126 "       return TexCoord;\n"
1127 "#endif\n"
1128 "}\n"
1129 "#endif // USEOFFSETMAPPING\n"
1130 "\n"
1131 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1132 "uniform sampler2D Texture_Attenuation;\n"
1133 "uniform samplerCube Texture_Cube;\n"
1134 "#endif\n"
1135 "\n"
1136 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1137 "\n"
1138 "#ifdef USESHADOWMAPRECT\n"
1139 "# ifdef USESHADOWSAMPLER\n"
1140 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1141 "# else\n"
1142 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1143 "# endif\n"
1144 "#endif\n"
1145 "\n"
1146 "#ifdef USESHADOWMAP2D\n"
1147 "# ifdef USESHADOWSAMPLER\n"
1148 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1149 "# else\n"
1150 "uniform sampler2D Texture_ShadowMap2D;\n"
1151 "# endif\n"
1152 "#endif\n"
1153 "\n"
1154 "#ifdef USESHADOWMAPVSDCT\n"
1155 "uniform samplerCube Texture_CubeProjection;\n"
1156 "#endif\n"
1157 "\n"
1158 "#ifdef USESHADOWMAPCUBE\n"
1159 "# ifdef USESHADOWSAMPLER\n"
1160 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1161 "# else\n"
1162 "uniform samplerCube Texture_ShadowMapCube;\n"
1163 "# endif\n"
1164 "#endif\n"
1165 "\n"
1166 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1167 "uniform vec2 ShadowMap_TextureScale;\n"
1168 "uniform vec4 ShadowMap_Parameters;\n"
1169 "#endif\n"
1170 "\n"
1171 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1172 "# ifdef USESHADOWMAPORTHO\n"
1173 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1174 "# else\n"
1175 "#  ifdef USESHADOWMAPVSDCT\n"
1176 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1177 "{\n"
1178 "       vec3 adir = abs(dir);\n"
1179 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1180 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1181 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1182 "}\n"
1183 "#  else\n"
1184 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1185 "{\n"
1186 "       vec3 adir = abs(dir);\n"
1187 "       float ma = adir.z;\n"
1188 "       vec4 proj = vec4(dir, 2.5);\n"
1189 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1190 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1191 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1192 "       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"
1193 "}\n"
1194 "#  endif\n"
1195 "# endif\n"
1196 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1197 "\n"
1198 "#ifdef USESHADOWMAPCUBE\n"
1199 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1200 "{\n"
1201 "       vec3 adir = abs(dir);\n"
1202 "       return vec4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
1203 "}\n"
1204 "#endif\n"
1205 "\n"
1206 "# ifdef USESHADOWMAPRECT\n"
1207 "float ShadowMapCompare(vec3 dir)\n"
1208 "{\n"
1209 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1210 "       float f;\n"
1211 "#  ifdef USESHADOWSAMPLER\n"
1212 "\n"
1213 "#    ifdef USESHADOWMAPPCF\n"
1214 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1215 "       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"
1216 "#    else\n"
1217 "       f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1218 "#    endif\n"
1219 "\n"
1220 "#  else\n"
1221 "\n"
1222 "#    ifdef USESHADOWMAPPCF\n"
1223 "#      if USESHADOWMAPPCF > 1\n"
1224 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1225 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1226 "       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"
1227 "       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"
1228 "       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"
1229 "       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"
1230 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1231 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1232 "#      else\n"
1233 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1234 "       vec2 offset = fract(shadowmaptc.xy);\n"
1235 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1236 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1237 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1238 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1239 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1240 "#      endif\n"
1241 "#    else\n"
1242 "       f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1243 "#    endif\n"
1244 "\n"
1245 "#  endif\n"
1246 "#  ifdef USESHADOWMAPORTHO\n"
1247 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1248 "#  else\n"
1249 "       return f;\n"
1250 "#  endif\n"
1251 "}\n"
1252 "# endif\n"
1253 "\n"
1254 "# ifdef USESHADOWMAP2D\n"
1255 "float ShadowMapCompare(vec3 dir)\n"
1256 "{\n"
1257 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1258 "       float f;\n"
1259 "\n"
1260 "#  ifdef USESHADOWSAMPLER\n"
1261 "#    ifdef USESHADOWMAPPCF\n"
1262 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1263 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1264 "       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"
1265 "#    else\n"
1266 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1267 "#    endif\n"
1268 "#  else\n"
1269 "#    ifdef USESHADOWMAPPCF\n"
1270 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1271 "#      ifdef GL_ARB_texture_gather\n"
1272 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1273 "#      else\n"
1274 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1275 "#      endif\n"
1276 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1277 "#      if USESHADOWMAPPCF > 1\n"
1278 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1279 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1280 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1281 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
1282 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
1283 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
1284 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
1285 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
1286 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
1287 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
1288 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
1289 "       locols.yz += group2.ab;\n"
1290 "       hicols.yz += group8.rg;\n"
1291 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1292 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1293 "                               mix(locols, hicols, offset.y);\n"
1294 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1295 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1296 "       f = dot(cols, vec4(1.0/25.0));\n"
1297 "#      else\n"
1298 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1299 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1300 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1301 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1302 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1303 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1304 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1305 "#      endif\n"
1306 "#     else\n"
1307 "#      ifdef GL_EXT_gpu_shader4\n"
1308 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1309 "#      else\n"
1310 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1311 "#      endif\n"
1312 "#      if USESHADOWMAPPCF > 1\n"
1313 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1314 "       center *= ShadowMap_TextureScale;\n"
1315 "       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"
1316 "       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"
1317 "       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"
1318 "       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"
1319 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1320 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1321 "#      else\n"
1322 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1323 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1324 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1325 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1326 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1327 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1328 "#      endif\n"
1329 "#     endif\n"
1330 "#    else\n"
1331 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1332 "#    endif\n"
1333 "#  endif\n"
1334 "#  ifdef USESHADOWMAPORTHO\n"
1335 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1336 "#  else\n"
1337 "       return f;\n"
1338 "#  endif\n"
1339 "}\n"
1340 "# endif\n"
1341 "\n"
1342 "# ifdef USESHADOWMAPCUBE\n"
1343 "float ShadowMapCompare(vec3 dir)\n"
1344 "{\n"
1345 "       // apply depth texture cubemap as light filter\n"
1346 "       vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1347 "       float f;\n"
1348 "#  ifdef USESHADOWSAMPLER\n"
1349 "       f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1350 "#  else\n"
1351 "       f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1352 "#  endif\n"
1353 "       return f;\n"
1354 "}\n"
1355 "# endif\n"
1356 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1357 "#endif // FRAGMENT_SHADER\n"
1358 "\n"
1359 "\n"
1360 "\n"
1361 "\n"
1362 "#ifdef MODE_DEFERREDGEOMETRY\n"
1363 "#ifdef VERTEX_SHADER\n"
1364 "uniform mat4 TexMatrix;\n"
1365 "#ifdef USEVERTEXTEXTUREBLEND\n"
1366 "uniform mat4 BackgroundTexMatrix;\n"
1367 "#endif\n"
1368 "uniform mat4 ModelViewMatrix;\n"
1369 "void main(void)\n"
1370 "{\n"
1371 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1372 "#ifdef USEVERTEXTEXTUREBLEND\n"
1373 "       gl_FrontColor = gl_Color;\n"
1374 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1375 "#endif\n"
1376 "\n"
1377 "       // transform unnormalized eye direction into tangent space\n"
1378 "#ifdef USEOFFSETMAPPING\n"
1379 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1380 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1381 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1382 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1383 "#endif\n"
1384 "\n"
1385 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1386 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1387 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1388 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1389 "}\n"
1390 "#endif // VERTEX_SHADER\n"
1391 "\n"
1392 "#ifdef FRAGMENT_SHADER\n"
1393 "void main(void)\n"
1394 "{\n"
1395 "#ifdef USEOFFSETMAPPING\n"
1396 "       // apply offsetmapping\n"
1397 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1398 "#define TexCoord TexCoordOffset\n"
1399 "#endif\n"
1400 "\n"
1401 "#ifdef USEALPHAKILL\n"
1402 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1403 "               discard;\n"
1404 "#endif\n"
1405 "\n"
1406 "#ifdef USEVERTEXTEXTUREBLEND\n"
1407 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1408 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1409 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1410 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1411 "#endif\n"
1412 "\n"
1413 "#ifdef USEVERTEXTEXTUREBLEND\n"
1414 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1415 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1416 "#else\n"
1417 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1418 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1419 "#endif\n"
1420 "\n"
1421 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1422 "}\n"
1423 "#endif // FRAGMENT_SHADER\n"
1424 "#else // !MODE_DEFERREDGEOMETRY\n"
1425 "\n"
1426 "\n"
1427 "\n"
1428 "\n"
1429 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1430 "#ifdef VERTEX_SHADER\n"
1431 "uniform mat4 ModelViewMatrix;\n"
1432 "void main(void)\n"
1433 "{\n"
1434 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1435 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1436 "}\n"
1437 "#endif // VERTEX_SHADER\n"
1438 "\n"
1439 "#ifdef FRAGMENT_SHADER\n"
1440 "uniform mat4 ViewToLight;\n"
1441 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1442 "uniform vec2 ScreenToDepth;\n"
1443 "uniform myhalf3 DeferredColor_Ambient;\n"
1444 "uniform myhalf3 DeferredColor_Diffuse;\n"
1445 "#ifdef USESPECULAR\n"
1446 "uniform myhalf3 DeferredColor_Specular;\n"
1447 "uniform myhalf SpecularPower;\n"
1448 "#endif\n"
1449 "uniform myhalf2 PixelToScreenTexCoord;\n"
1450 "void main(void)\n"
1451 "{\n"
1452 "       // calculate viewspace pixel position\n"
1453 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1454 "       vec3 position;\n"
1455 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1456 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1457 "       // decode viewspace pixel normal\n"
1458 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1459 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1460 "       // surfacenormal = pixel normal in viewspace\n"
1461 "       // LightVector = pixel to light in viewspace\n"
1462 "       // CubeVector = position in lightspace\n"
1463 "       // eyevector = pixel to view in viewspace\n"
1464 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1465 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1466 "#ifdef USEDIFFUSE\n"
1467 "       // calculate diffuse shading\n"
1468 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1469 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1470 "#endif\n"
1471 "#ifdef USESPECULAR\n"
1472 "       // calculate directional shading\n"
1473 "       vec3 eyevector = position * -1.0;\n"
1474 "#  ifdef USEEXACTSPECULARMATH\n"
1475 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1476 "#  else\n"
1477 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1478 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1479 "#  endif\n"
1480 "#endif\n"
1481 "\n"
1482 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1483 "       fade *= ShadowMapCompare(CubeVector);\n"
1484 "#endif\n"
1485 "\n"
1486 "#ifdef USEDIFFUSE\n"
1487 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1488 "#else\n"
1489 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1490 "#endif\n"
1491 "#ifdef USESPECULAR\n"
1492 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1493 "#else\n"
1494 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1495 "#endif\n"
1496 "\n"
1497 "# ifdef USECUBEFILTER\n"
1498 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1499 "       gl_FragData[0].rgb *= cubecolor;\n"
1500 "       gl_FragData[1].rgb *= cubecolor;\n"
1501 "# endif\n"
1502 "}\n"
1503 "#endif // FRAGMENT_SHADER\n"
1504 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1505 "\n"
1506 "\n"
1507 "\n"
1508 "\n"
1509 "#ifdef VERTEX_SHADER\n"
1510 "uniform mat4 TexMatrix;\n"
1511 "#ifdef USEVERTEXTEXTUREBLEND\n"
1512 "uniform mat4 BackgroundTexMatrix;\n"
1513 "#endif\n"
1514 "#ifdef MODE_LIGHTSOURCE\n"
1515 "uniform mat4 ModelToLight;\n"
1516 "#endif\n"
1517 "#ifdef USESHADOWMAPORTHO\n"
1518 "uniform mat4 ShadowMapMatrix;\n"
1519 "#endif\n"
1520 "void main(void)\n"
1521 "{\n"
1522 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1523 "       gl_FrontColor = gl_Color;\n"
1524 "#endif\n"
1525 "       // copy the surface texcoord\n"
1526 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1527 "#ifdef USEVERTEXTEXTUREBLEND\n"
1528 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1529 "#endif\n"
1530 "#ifdef USELIGHTMAP\n"
1531 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1532 "#endif\n"
1533 "\n"
1534 "#ifdef MODE_LIGHTSOURCE\n"
1535 "       // transform vertex position into light attenuation/cubemap space\n"
1536 "       // (-1 to +1 across the light box)\n"
1537 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1538 "\n"
1539 "# ifdef USEDIFFUSE\n"
1540 "       // transform unnormalized light direction into tangent space\n"
1541 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1542 "       //  normalize it per pixel)\n"
1543 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1544 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1545 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1546 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1547 "# endif\n"
1548 "#endif\n"
1549 "\n"
1550 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1551 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1552 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1553 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1554 "#endif\n"
1555 "\n"
1556 "       // transform unnormalized eye direction into tangent space\n"
1557 "#ifdef USEEYEVECTOR\n"
1558 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1559 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1560 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1561 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1562 "#endif\n"
1563 "\n"
1564 "#ifdef USEFOG\n"
1565 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1566 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1567 "#endif\n"
1568 "\n"
1569 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1570 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1571 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1572 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1573 "#endif\n"
1574 "\n"
1575 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1576 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1577 "\n"
1578 "#ifdef USESHADOWMAPORTHO\n"
1579 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1580 "#endif\n"
1581 "\n"
1582 "#ifdef USEREFLECTION\n"
1583 "       ModelViewProjectionPosition = gl_Position;\n"
1584 "#endif\n"
1585 "}\n"
1586 "#endif // VERTEX_SHADER\n"
1587 "\n"
1588 "\n"
1589 "\n"
1590 "\n"
1591 "#ifdef FRAGMENT_SHADER\n"
1592 "#ifdef USEDEFERREDLIGHTMAP\n"
1593 "uniform myhalf2 PixelToScreenTexCoord;\n"
1594 "uniform myhalf3 DeferredMod_Diffuse;\n"
1595 "uniform myhalf3 DeferredMod_Specular;\n"
1596 "#endif\n"
1597 "uniform myhalf3 Color_Ambient;\n"
1598 "uniform myhalf3 Color_Diffuse;\n"
1599 "uniform myhalf3 Color_Specular;\n"
1600 "uniform myhalf SpecularPower;\n"
1601 "#ifdef USEGLOW\n"
1602 "uniform myhalf3 Color_Glow;\n"
1603 "#endif\n"
1604 "uniform myhalf Alpha;\n"
1605 "#ifdef USEREFLECTION\n"
1606 "uniform vec4 DistortScaleRefractReflect;\n"
1607 "uniform vec4 ScreenScaleRefractReflect;\n"
1608 "uniform vec4 ScreenCenterRefractReflect;\n"
1609 "uniform myhalf4 ReflectColor;\n"
1610 "#endif\n"
1611 "#ifdef USEREFLECTCUBE\n"
1612 "uniform mat4 ModelToReflectCube;\n"
1613 "uniform sampler2D Texture_ReflectMask;\n"
1614 "uniform samplerCube Texture_ReflectCube;\n"
1615 "#endif\n"
1616 "#ifdef MODE_LIGHTDIRECTION\n"
1617 "uniform myhalf3 LightColor;\n"
1618 "#endif\n"
1619 "#ifdef MODE_LIGHTSOURCE\n"
1620 "uniform myhalf3 LightColor;\n"
1621 "#endif\n"
1622 "void main(void)\n"
1623 "{\n"
1624 "#ifdef USEOFFSETMAPPING\n"
1625 "       // apply offsetmapping\n"
1626 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1627 "#define TexCoord TexCoordOffset\n"
1628 "#endif\n"
1629 "\n"
1630 "       // combine the diffuse textures (base, pants, shirt)\n"
1631 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1632 "#ifdef USEALPHAKILL\n"
1633 "       if (color.a < 0.5)\n"
1634 "               discard;\n"
1635 "#endif\n"
1636 "       color.a *= Alpha;\n"
1637 "#ifdef USECOLORMAPPING\n"
1638 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1639 "#endif\n"
1640 "#ifdef USEVERTEXTEXTUREBLEND\n"
1641 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1642 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1643 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1644 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1645 "       color.a = 1.0;\n"
1646 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1647 "#endif\n"
1648 "\n"
1649 "       // get the surface normal\n"
1650 "#ifdef USEVERTEXTEXTUREBLEND\n"
1651 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1652 "#else\n"
1653 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1654 "#endif\n"
1655 "\n"
1656 "       // get the material colors\n"
1657 "       myhalf3 diffusetex = color.rgb;\n"
1658 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1659 "# ifdef USEVERTEXTEXTUREBLEND\n"
1660 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1661 "# else\n"
1662 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1663 "# endif\n"
1664 "#endif\n"
1665 "\n"
1666 "#ifdef USEREFLECTCUBE\n"
1667 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1668 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1669 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1670 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1671 "#endif\n"
1672 "\n"
1673 "\n"
1674 "\n"
1675 "\n"
1676 "#ifdef MODE_LIGHTSOURCE\n"
1677 "       // light source\n"
1678 "#ifdef USEDIFFUSE\n"
1679 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1680 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1681 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1682 "#ifdef USESPECULAR\n"
1683 "#ifdef USEEXACTSPECULARMATH\n"
1684 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1685 "#else\n"
1686 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1687 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1688 "#endif\n"
1689 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1690 "#endif\n"
1691 "#else\n"
1692 "       color.rgb = diffusetex * Color_Ambient;\n"
1693 "#endif\n"
1694 "       color.rgb *= LightColor;\n"
1695 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1696 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1697 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1698 "#endif\n"
1699 "# ifdef USECUBEFILTER\n"
1700 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1701 "# endif\n"
1702 "#endif // MODE_LIGHTSOURCE\n"
1703 "\n"
1704 "\n"
1705 "\n"
1706 "\n"
1707 "#ifdef MODE_LIGHTDIRECTION\n"
1708 "#define SHADING\n"
1709 "#ifdef USEDIFFUSE\n"
1710 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1711 "#endif\n"
1712 "#define lightcolor LightColor\n"
1713 "#endif // MODE_LIGHTDIRECTION\n"
1714 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1715 "#define SHADING\n"
1716 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1717 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1718 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1719 "       // convert modelspace light vector to tangentspace\n"
1720 "       myhalf3 lightnormal;\n"
1721 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1722 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1723 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1724 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1725 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1726 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1727 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1728 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1729 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1730 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1731 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1732 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1733 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1734 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1735 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1736 "#define SHADING\n"
1737 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1738 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1739 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1740 "#endif\n"
1741 "\n"
1742 "\n"
1743 "\n"
1744 "\n"
1745 "#ifdef MODE_LIGHTMAP\n"
1746 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1747 "#endif // MODE_LIGHTMAP\n"
1748 "#ifdef MODE_VERTEXCOLOR\n"
1749 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1750 "#endif // MODE_VERTEXCOLOR\n"
1751 "#ifdef MODE_FLATCOLOR\n"
1752 "       color.rgb = diffusetex * Color_Ambient;\n"
1753 "#endif // MODE_FLATCOLOR\n"
1754 "\n"
1755 "\n"
1756 "\n"
1757 "\n"
1758 "#ifdef SHADING\n"
1759 "# ifdef USEDIFFUSE\n"
1760 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1761 "#  ifdef USESPECULAR\n"
1762 "#   ifdef USEEXACTSPECULARMATH\n"
1763 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1764 "#   else\n"
1765 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1766 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1767 "#   endif\n"
1768 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1769 "#  else\n"
1770 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1771 "#  endif\n"
1772 "# else\n"
1773 "       color.rgb = diffusetex * Color_Ambient;\n"
1774 "# endif\n"
1775 "#endif\n"
1776 "\n"
1777 "#ifdef USESHADOWMAPORTHO\n"
1778 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1779 "#endif\n"
1780 "\n"
1781 "#ifdef USEDEFERREDLIGHTMAP\n"
1782 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1783 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1784 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1785 "#endif\n"
1786 "\n"
1787 "#ifdef USEGLOW\n"
1788 "#ifdef USEVERTEXTEXTUREBLEND\n"
1789 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1790 "#else\n"
1791 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1792 "#endif\n"
1793 "#endif\n"
1794 "\n"
1795 "#ifdef USEFOG\n"
1796 "       color.rgb = FogVertex(color.rgb);\n"
1797 "#endif\n"
1798 "\n"
1799 "       // 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"
1800 "#ifdef USEREFLECTION\n"
1801 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1802 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1803 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1804 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1805 "       // FIXME temporary hack to detect the case that the reflection\n"
1806 "       // gets blackened at edges due to leaving the area that contains actual\n"
1807 "       // content.\n"
1808 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1809 "       // 'appening.\n"
1810 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1811 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1812 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1813 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1814 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1815 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1816 "#endif\n"
1817 "\n"
1818 "       gl_FragColor = vec4(color);\n"
1819 "}\n"
1820 "#endif // FRAGMENT_SHADER\n"
1821 "\n"
1822 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1823 "#endif // !MODE_DEFERREDGEOMETRY\n"
1824 "#endif // !MODE_WATER\n"
1825 "#endif // !MODE_REFRACTION\n"
1826 "#endif // !MODE_BLOOMBLUR\n"
1827 "#endif // !MODE_GENERIC\n"
1828 "#endif // !MODE_POSTPROCESS\n"
1829 "#endif // !MODE_SHOWDEPTH\n"
1830 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1831 ;
1832
1833 /*
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 const char *builtincgshaderstring =
1862 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1863 "// written by Forest 'LordHavoc' Hale\n"
1864 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1865 "\n"
1866 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1867 "#if defined(USEREFLECTION)\n"
1868 "#undef USESHADOWMAPORTHO\n"
1869 "#endif\n"
1870 "\n"
1871 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1872 "# define USEFOG\n"
1873 "#endif\n"
1874 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1875 "#define USELIGHTMAP\n"
1876 "#endif\n"
1877 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
1878 "#define USEEYEVECTOR\n"
1879 "#endif\n"
1880 "\n"
1881 "#ifdef FRAGMENT_SHADER\n"
1882 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1883 "#endif\n"
1884 "\n"
1885 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1886 "#ifdef VERTEX_SHADER\n"
1887 "void main\n"
1888 "(\n"
1889 "float4 gl_Vertex : POSITION,\n"
1890 "uniform float4x4 ModelViewProjectionMatrix,\n"
1891 "out float4 gl_Position : POSITION\n"
1892 ")\n"
1893 "{\n"
1894 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1895 "}\n"
1896 "#endif\n"
1897 "#else // !MODE_DEPTH_ORSHADOW\n"
1898 "\n"
1899 "\n"
1900 "\n"
1901 "\n"
1902 "#ifdef MODE_SHOWDEPTH\n"
1903 "#ifdef VERTEX_SHADER\n"
1904 "void main\n"
1905 "(\n"
1906 "float4 gl_Vertex : POSITION,\n"
1907 "uniform float4x4 ModelViewProjectionMatrix,\n"
1908 "out float4 gl_Position : POSITION,\n"
1909 "out float4 gl_FrontColor : COLOR0\n"
1910 ")\n"
1911 "{\n"
1912 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1913 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1914 "}\n"
1915 "#endif\n"
1916 "\n"
1917 "#ifdef FRAGMENT_SHADER\n"
1918 "void main\n"
1919 "(\n"
1920 "float4 gl_FrontColor : COLOR0,\n"
1921 "out float4 gl_FragColor : COLOR\n"
1922 ")\n"
1923 "{\n"
1924 "       gl_FragColor = gl_FrontColor;\n"
1925 "}\n"
1926 "#endif\n"
1927 "#else // !MODE_SHOWDEPTH\n"
1928 "\n"
1929 "\n"
1930 "\n"
1931 "\n"
1932 "#ifdef MODE_POSTPROCESS\n"
1933 "\n"
1934 "#ifdef VERTEX_SHADER\n"
1935 "void main\n"
1936 "(\n"
1937 "float4 gl_Vertex : POSITION,\n"
1938 "uniform float4x4 ModelViewProjectionMatrix,\n"
1939 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1940 "float4 gl_MultiTexCoord1 : TEXCOORD4,\n"
1941 "out float4 gl_Position : POSITION,\n"
1942 "out float2 TexCoord1 : TEXCOORD0,\n"
1943 "out float2 TexCoord2 : TEXCOORD1\n"
1944 ")\n"
1945 "{\n"
1946 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1947 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1948 "#ifdef USEBLOOM\n"
1949 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1950 "#endif\n"
1951 "}\n"
1952 "#endif\n"
1953 "\n"
1954 "#ifdef FRAGMENT_SHADER\n"
1955 "void main\n"
1956 "(\n"
1957 "float2 TexCoord1 : TEXCOORD0,\n"
1958 "float2 TexCoord2 : TEXCOORD1,\n"
1959 "uniform sampler2D Texture_First,\n"
1960 "#ifdef USEBLOOM\n"
1961 "uniform sampler2D Texture_Second,\n"
1962 "#endif\n"
1963 "#ifdef USEGAMMARAMPS\n"
1964 "uniform sampler2D Texture_GammaRamps,\n"
1965 "#endif\n"
1966 "#ifdef USESATURATION\n"
1967 "uniform float Saturation,\n"
1968 "#endif\n"
1969 "#ifdef USEVIEWTINT\n"
1970 "uniform float4 ViewTintColor,\n"
1971 "#endif\n"
1972 "uniform float4 UserVec1,\n"
1973 "uniform float4 UserVec2,\n"
1974 "uniform float4 UserVec3,\n"
1975 "uniform float4 UserVec4,\n"
1976 "uniform float ClientTime,\n"
1977 "uniform float2 PixelSize,\n"
1978 "out float4 gl_FragColor : COLOR\n"
1979 ")\n"
1980 "{\n"
1981 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1982 "#ifdef USEBLOOM\n"
1983 "       gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
1984 "#endif\n"
1985 "#ifdef USEVIEWTINT\n"
1986 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1987 "#endif\n"
1988 "\n"
1989 "#ifdef USEPOSTPROCESSING\n"
1990 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1991 "// 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"
1992 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1993 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1994 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1995 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
1996 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
1997 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
1998 "#endif\n"
1999 "\n"
2000 "#ifdef USESATURATION\n"
2001 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2002 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2003 "       //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2004 "       gl_FragColor.rgb = lerp(float3(y), gl_FragColor.rgb, Saturation);\n"
2005 "#endif\n"
2006 "\n"
2007 "#ifdef USEGAMMARAMPS\n"
2008 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2009 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2010 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2011 "#endif\n"
2012 "}\n"
2013 "#endif\n"
2014 "#else // !MODE_POSTPROCESS\n"
2015 "\n"
2016 "\n"
2017 "\n"
2018 "\n"
2019 "#ifdef MODE_GENERIC\n"
2020 "#ifdef VERTEX_SHADER\n"
2021 "void main\n"
2022 "(\n"
2023 "float4 gl_Vertex : POSITION,\n"
2024 "uniform float4x4 ModelViewProjectionMatrix,\n"
2025 "float4 gl_Color : COLOR0,\n"
2026 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2027 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2028 "out float4 gl_Position : POSITION,\n"
2029 "out float4 gl_FrontColor : COLOR,\n"
2030 "out float2 TexCoord1 : TEXCOORD0,\n"
2031 "out float2 TexCoord2 : TEXCOORD1\n"
2032 ")\n"
2033 "{\n"
2034 "       gl_FrontColor = gl_Color;\n"
2035 "#ifdef USEDIFFUSE\n"
2036 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2037 "#endif\n"
2038 "#ifdef USESPECULAR\n"
2039 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
2040 "#endif\n"
2041 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2042 "}\n"
2043 "#endif\n"
2044 "\n"
2045 "#ifdef FRAGMENT_SHADER\n"
2046 "\n"
2047 "void main\n"
2048 "(\n"
2049 "float4 gl_FrontColor : COLOR,\n"
2050 "float2 TexCoord1 : TEXCOORD0,\n"
2051 "float2 TexCoord2 : TEXCOORD1,\n"
2052 "#ifdef USEDIFFUSE\n"
2053 "uniform sampler2D Texture_First,\n"
2054 "#endif\n"
2055 "#ifdef USESPECULAR\n"
2056 "uniform sampler2D Texture_Second,\n"
2057 "#endif\n"
2058 "out float4 gl_FragColor : COLOR\n"
2059 ")\n"
2060 "{\n"
2061 "       gl_FragColor = gl_FrontColor;\n"
2062 "#ifdef USEDIFFUSE\n"
2063 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2064 "#endif\n"
2065 "\n"
2066 "#ifdef USESPECULAR\n"
2067 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2068 "# ifdef USECOLORMAPPING\n"
2069 "       gl_FragColor *= tex2;\n"
2070 "# endif\n"
2071 "# ifdef USEGLOW\n"
2072 "       gl_FragColor += tex2;\n"
2073 "# endif\n"
2074 "# ifdef USEVERTEXTEXTUREBLEND\n"
2075 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2076 "# endif\n"
2077 "#endif\n"
2078 "}\n"
2079 "#endif\n"
2080 "#else // !MODE_GENERIC\n"
2081 "\n"
2082 "\n"
2083 "\n"
2084 "\n"
2085 "#ifdef MODE_BLOOMBLUR\n"
2086 "#ifdef VERTEX_SHADER\n"
2087 "void main\n"
2088 "(\n"
2089 "float4 gl_Vertex : POSITION,\n"
2090 "uniform float4x4 ModelViewProjectionMatrix,\n"
2091 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2092 "out float4 gl_Position : POSITION,\n"
2093 "out float2 TexCoord : TEXCOORD0\n"
2094 ")\n"
2095 "{\n"
2096 "       TexCoord = gl_MultiTexCoord0.xy;\n"
2097 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2098 "}\n"
2099 "#endif\n"
2100 "\n"
2101 "#ifdef FRAGMENT_SHADER\n"
2102 "\n"
2103 "void main\n"
2104 "(\n"
2105 "float2 TexCoord : TEXCOORD0,\n"
2106 "uniform sampler2D Texture_First,\n"
2107 "uniform float4 BloomBlur_Parameters,\n"
2108 "out float4 gl_FragColor : COLOR\n"
2109 ")\n"
2110 "{\n"
2111 "       int i;\n"
2112 "       float2 tc = TexCoord;\n"
2113 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2114 "       tc += BloomBlur_Parameters.xy;\n"
2115 "       for (i = 1;i < SAMPLES;i++)\n"
2116 "       {\n"
2117 "               color += tex2D(Texture_First, tc).rgb;\n"
2118 "               tc += BloomBlur_Parameters.xy;\n"
2119 "       }\n"
2120 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2121 "}\n"
2122 "#endif\n"
2123 "#else // !MODE_BLOOMBLUR\n"
2124 "#ifdef MODE_REFRACTION\n"
2125 "#ifdef VERTEX_SHADER\n"
2126 "void main\n"
2127 "(\n"
2128 "float4 gl_Vertex : POSITION,\n"
2129 "uniform float4x4 ModelViewProjectionMatrix,\n"
2130 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2131 "uniform float4x4 TexMatrix,\n"
2132 "uniform float3 EyePosition,\n"
2133 "out float4 gl_Position : POSITION,\n"
2134 "out float2 TexCoord : TEXCOORD0,\n"
2135 "out float3 EyeVector : TEXCOORD1,\n"
2136 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2137 ")\n"
2138 "{\n"
2139 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2140 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2141 "       ModelViewProjectionPosition = gl_Position;\n"
2142 "}\n"
2143 "#endif\n"
2144 "\n"
2145 "#ifdef FRAGMENT_SHADER\n"
2146 "void main\n"
2147 "(\n"
2148 "float2 TexCoord : TEXCOORD0,\n"
2149 "float3 EyeVector : TEXCOORD1,\n"
2150 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2151 "uniform sampler2D Texture_Normal,\n"
2152 "uniform sampler2D Texture_Refraction,\n"
2153 "uniform sampler2D Texture_Reflection,\n"
2154 "uniform float4 DistortScaleRefractReflect,\n"
2155 "uniform float4 ScreenScaleRefractReflect,\n"
2156 "uniform float4 ScreenCenterRefractReflect,\n"
2157 "uniform float4 RefractColor,\n"
2158 "out float4 gl_FragColor : COLOR\n"
2159 ")\n"
2160 "{\n"
2161 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2162 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2163 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2164 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
2165 "       // FIXME temporary hack to detect the case that the reflection\n"
2166 "       // gets blackened at edges due to leaving the area that contains actual\n"
2167 "       // content.\n"
2168 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2169 "       // 'appening.\n"
2170 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2171 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2172 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2173 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2174 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2175 "       gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2176 "}\n"
2177 "#endif\n"
2178 "#else // !MODE_REFRACTION\n"
2179 "\n"
2180 "\n"
2181 "\n"
2182 "\n"
2183 "#ifdef MODE_WATER\n"
2184 "#ifdef VERTEX_SHADER\n"
2185 "\n"
2186 "void main\n"
2187 "(\n"
2188 "float4 gl_Vertex : POSITION,\n"
2189 "uniform float4x4 ModelViewProjectionMatrix,\n"
2190 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2191 "uniform float4x4 TexMatrix,\n"
2192 "uniform float3 EyePosition,\n"
2193 "out float4 gl_Position : POSITION,\n"
2194 "out float2 TexCoord : TEXCOORD0,\n"
2195 "out float3 EyeVector : TEXCOORD1,\n"
2196 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2197 ")\n"
2198 "{\n"
2199 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2200 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2201 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2202 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2203 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2204 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2205 "       ModelViewProjectionPosition = gl_Position;\n"
2206 "}\n"
2207 "#endif\n"
2208 "\n"
2209 "#ifdef FRAGMENT_SHADER\n"
2210 "void main\n"
2211 "(\n"
2212 "float2 TexCoord : TEXCOORD0,\n"
2213 "float3 EyeVector : TEXCOORD1,\n"
2214 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2215 "uniform sampler2D Texture_Normal,\n"
2216 "uniform sampler2D Texture_Refraction,\n"
2217 "uniform sampler2D Texture_Reflection,\n"
2218 "uniform float4 DistortScaleRefractReflect,\n"
2219 "uniform float4 ScreenScaleRefractReflect,\n"
2220 "uniform float4 ScreenCenterRefractReflect,\n"
2221 "uniform float4 RefractColor,\n"
2222 "uniform float4 ReflectColor,\n"
2223 "uniform float ReflectFactor,\n"
2224 "uniform float ReflectOffset,\n"
2225 "out float4 gl_FragColor : COLOR\n"
2226 ")\n"
2227 "{\n"
2228 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2229 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2230 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2231 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xyxy * DistortScaleRefractReflect;\n"
2232 "       // FIXME temporary hack to detect the case that the reflection\n"
2233 "       // gets blackened at edges due to leaving the area that contains actual\n"
2234 "       // content.\n"
2235 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2236 "       // 'appening.\n"
2237 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2238 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2239 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2240 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2241 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2242 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2243 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2244 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2245 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2246 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2247 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2248 "       gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2249 "}\n"
2250 "#endif\n"
2251 "#else // !MODE_WATER\n"
2252 "\n"
2253 "\n"
2254 "\n"
2255 "\n"
2256 "// 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"
2257 "\n"
2258 "// fragment shader specific:\n"
2259 "#ifdef FRAGMENT_SHADER\n"
2260 "\n"
2261 "#ifdef USEFOG\n"
2262 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask, sampler2D Texture_FogHeightTexture)\n"
2263 "{\n"
2264 "       float fogfrac;\n"
2265 "#ifdef USEFOGHEIGHTTEXTURE\n"
2266 "       float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2267 "       fogfrac = fogheightpixel.a;\n"
2268 "       return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2269 "#else\n"
2270 "# ifdef USEFOGOUTSIDE\n"
2271 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2272 "# else\n"
2273 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2274 "# endif\n"
2275 "       return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2276 "#endif\n"
2277 "}\n"
2278 "#endif\n"
2279 "\n"
2280 "#ifdef USEOFFSETMAPPING\n"
2281 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler2D Texture_Normal)\n"
2282 "{\n"
2283 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2284 "       // 14 sample relief mapping: linear search and then binary search\n"
2285 "       // this basically steps forward a small amount repeatedly until it finds\n"
2286 "       // itself inside solid, then jitters forward and back using decreasing\n"
2287 "       // amounts to find the impact\n"
2288 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2289 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2290 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2291 "       float3 RT = float3(TexCoord, 1);\n"
2292 "       OffsetVector *= 0.1;\n"
2293 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2294 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2295 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\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)          - 0.5);\n"
2303 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2304 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2305 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2306 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2307 "       return RT.xy;\n"
2308 "#else\n"
2309 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2310 "       // this basically moves forward the full distance, and then backs up based\n"
2311 "       // on height of samples\n"
2312 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2313 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2314 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2315 "       TexCoord += OffsetVector;\n"
2316 "       OffsetVector *= 0.333;\n"
2317 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2318 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2319 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2320 "       return TexCoord;\n"
2321 "#endif\n"
2322 "}\n"
2323 "#endif // USEOFFSETMAPPING\n"
2324 "\n"
2325 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2326 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2327 "# ifdef USESHADOWMAPORTHO\n"
2328 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2329 "# else\n"
2330 "#  ifdef USESHADOWMAPVSDCT\n"
2331 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2332 "{\n"
2333 "       float3 adir = abs(dir);\n"
2334 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2335 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2336 "       return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2337 "}\n"
2338 "#  else\n"
2339 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2340 "{\n"
2341 "       float3 adir = abs(dir);\n"
2342 "       float ma = adir.z;\n"
2343 "       float4 proj = float4(dir, 2.5);\n"
2344 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2345 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2346 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2347 "       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"
2348 "}\n"
2349 "#  endif\n"
2350 "# endif\n"
2351 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2352 "\n"
2353 "#ifdef USESHADOWMAPCUBE\n"
2354 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2355 "{\n"
2356 "    float3 adir = abs(dir);\n"
2357 "    return float4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
2358 "}\n"
2359 "#endif\n"
2360 "\n"
2361 "# ifdef USESHADOWMAPRECT\n"
2362 "#ifdef USESHADOWMAPVSDCT\n"
2363 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2364 "#else\n"
2365 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2366 "#endif\n"
2367 "{\n"
2368 "#ifdef USESHADOWMAPVSDCT\n"
2369 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2370 "#else\n"
2371 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2372 "#endif\n"
2373 "       float f;\n"
2374 "#  ifdef USESHADOWSAMPLER\n"
2375 "\n"
2376 "#    ifdef USESHADOWMAPPCF\n"
2377 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2378 "    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"
2379 "#    else\n"
2380 "    f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2381 "#    endif\n"
2382 "\n"
2383 "#  else\n"
2384 "\n"
2385 "#    ifdef USESHADOWMAPPCF\n"
2386 "#      if USESHADOWMAPPCF > 1\n"
2387 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2388 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2389 "    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"
2390 "    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"
2391 "    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"
2392 "    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"
2393 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2394 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2395 "#      else\n"
2396 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2397 "    float2 offset = frac(shadowmaptc.xy);\n"
2398 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2399 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2400 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2401 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2402 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2403 "#      endif\n"
2404 "#    else\n"
2405 "    f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2406 "#    endif\n"
2407 "\n"
2408 "#  endif\n"
2409 "#  ifdef USESHADOWMAPORTHO\n"
2410 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2411 "#  else\n"
2412 "       return f;\n"
2413 "#  endif\n"
2414 "}\n"
2415 "# endif\n"
2416 "\n"
2417 "# ifdef USESHADOWMAP2D\n"
2418 "#ifdef USESHADOWMAPVSDCT\n"
2419 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2420 "#else\n"
2421 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2422 "#endif\n"
2423 "{\n"
2424 "#ifdef USESHADOWMAPVSDCT\n"
2425 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2426 "#else\n"
2427 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2428 "#endif\n"
2429 "    float f;\n"
2430 "\n"
2431 "#  ifdef USESHADOWSAMPLER\n"
2432 "#    ifdef USESHADOWMAPPCF\n"
2433 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, float3(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
2434 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2435 "    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"
2436 "#    else\n"
2437 "    f = shadow2D(Texture_ShadowMap2D, float3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
2438 "#    endif\n"
2439 "#  else\n"
2440 "#    ifdef USESHADOWMAPPCF\n"
2441 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2442 "#      ifdef GL_ARB_texture_gather\n"
2443 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
2444 "#      else\n"
2445 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x,y)*ShadowMap_TextureScale)\n"
2446 "#      endif\n"
2447 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2448 "    center *= ShadowMap_TextureScale;\n"
2449 "    float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2450 "    float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2451 "    float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2452 "    float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2453 "    float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2454 "                lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2455 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2456 "#     else\n"
2457 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)  \n"
2458 "#      if USESHADOWMAPPCF > 1\n"
2459 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2460 "    center *= ShadowMap_TextureScale;\n"
2461 "    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"
2462 "    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"
2463 "    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"
2464 "    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"
2465 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2466 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2467 "#      else\n"
2468 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2469 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2470 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2471 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2472 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2473 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2474 "#      endif\n"
2475 "#     endif\n"
2476 "#    else\n"
2477 "    f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2478 "#    endif\n"
2479 "#  endif\n"
2480 "#  ifdef USESHADOWMAPORTHO\n"
2481 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2482 "#  else\n"
2483 "       return f;\n"
2484 "#  endif\n"
2485 "}\n"
2486 "# endif\n"
2487 "\n"
2488 "# ifdef USESHADOWMAPCUBE\n"
2489 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2490 "{\n"
2491 "    // apply depth texture cubemap as light filter\n"
2492 "    float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2493 "    float f;\n"
2494 "#  ifdef USESHADOWSAMPLER\n"
2495 "    f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2496 "#  else\n"
2497 "    f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2498 "#  endif\n"
2499 "    return f;\n"
2500 "}\n"
2501 "# endif\n"
2502 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2503 "#endif // FRAGMENT_SHADER\n"
2504 "\n"
2505 "\n"
2506 "\n"
2507 "\n"
2508 "#ifdef MODE_DEFERREDGEOMETRY\n"
2509 "#ifdef VERTEX_SHADER\n"
2510 "void main\n"
2511 "(\n"
2512 "float4 gl_Vertex : POSITION,\n"
2513 "uniform float4x4 ModelViewProjectionMatrix,\n"
2514 "#ifdef USEVERTEXTEXTUREBLEND\n"
2515 "float4 gl_Color : COLOR0,\n"
2516 "#endif\n"
2517 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2518 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2519 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2520 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2521 "uniform float4x4 TexMatrix,\n"
2522 "#ifdef USEVERTEXTEXTUREBLEND\n"
2523 "uniform float4x4 BackgroundTexMatrix,\n"
2524 "#endif\n"
2525 "uniform float4x4 ModelViewMatrix,\n"
2526 "#ifdef USEOFFSETMAPPING\n"
2527 "uniform float3 EyePosition,\n"
2528 "#endif\n"
2529 "out float4 gl_Position : POSITION,\n"
2530 "out float4 gl_FrontColor : COLOR,\n"
2531 "out float4 TexCoordBoth : TEXCOORD0,\n"
2532 "#ifdef USEOFFSETMAPPING\n"
2533 "out float3 EyeVector : TEXCOORD2,\n"
2534 "#endif\n"
2535 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2536 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2537 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2538 ")\n"
2539 "{\n"
2540 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2541 "#ifdef USEVERTEXTEXTUREBLEND\n"
2542 "       gl_FrontColor = gl_Color;\n"
2543 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2544 "#endif\n"
2545 "\n"
2546 "       // transform unnormalized eye direction into tangent space\n"
2547 "#ifdef USEOFFSETMAPPING\n"
2548 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2549 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2550 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2551 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2552 "#endif\n"
2553 "\n"
2554 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2555 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2556 "       VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2557 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2558 "}\n"
2559 "#endif // VERTEX_SHADER\n"
2560 "\n"
2561 "#ifdef FRAGMENT_SHADER\n"
2562 "void main\n"
2563 "(\n"
2564 "float4 TexCoordBoth : TEXCOORD0,\n"
2565 "float3 EyeVector : TEXCOORD2,\n"
2566 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2567 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2568 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2569 "uniform sampler2D Texture_Normal,\n"
2570 "#ifdef USEALPHAKILL\n"
2571 "uniform sampler2D Texture_Color,\n"
2572 "#endif\n"
2573 "uniform sampler2D Texture_Gloss,\n"
2574 "#ifdef USEVERTEXTEXTUREBLEND\n"
2575 "uniform sampler2D Texture_SecondaryNormal,\n"
2576 "uniform sampler2D Texture_SecondaryGloss,\n"
2577 "#endif\n"
2578 "#ifdef USEOFFSETMAPPING\n"
2579 "uniform float OffsetMapping_Scale,\n"
2580 "#endif\n"
2581 "uniform half SpecularPower,\n"
2582 "out float4 gl_FragColor : COLOR\n"
2583 ")\n"
2584 "{\n"
2585 "       float2 TexCoord = TexCoordBoth.xy;\n"
2586 "#ifdef USEOFFSETMAPPING\n"
2587 "       // apply offsetmapping\n"
2588 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2589 "#define TexCoord TexCoordOffset\n"
2590 "#endif\n"
2591 "\n"
2592 "#ifdef USEALPHAKILL\n"
2593 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2594 "               discard;\n"
2595 "#endif\n"
2596 "\n"
2597 "#ifdef USEVERTEXTEXTUREBLEND\n"
2598 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2599 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2600 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2601 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2602 "#endif\n"
2603 "\n"
2604 "#ifdef USEVERTEXTEXTUREBLEND\n"
2605 "       float3 surfacenormal = lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
2606 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2607 "#else\n"
2608 "       float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
2609 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2610 "#endif\n"
2611 "\n"
2612 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), 1);\n"
2613 "}\n"
2614 "#endif // FRAGMENT_SHADER\n"
2615 "#else // !MODE_DEFERREDGEOMETRY\n"
2616 "\n"
2617 "\n"
2618 "\n"
2619 "\n"
2620 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2621 "#ifdef VERTEX_SHADER\n"
2622 "void main\n"
2623 "(\n"
2624 "float4 gl_Vertex : POSITION,\n"
2625 "uniform float4x4 ModelViewProjectionMatrix,\n"
2626 "uniform float4x4 ModelViewMatrix,\n"
2627 "out float4 gl_Position : POSITION,\n"
2628 "out float4 ModelViewPosition : TEXCOORD0\n"
2629 ")\n"
2630 "{\n"
2631 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2632 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2633 "}\n"
2634 "#endif // VERTEX_SHADER\n"
2635 "\n"
2636 "#ifdef FRAGMENT_SHADER\n"
2637 "void main\n"
2638 "(\n"
2639 "float2 Pixel : WPOS,\n"
2640 "float4 ModelViewPosition : TEXCOORD0,\n"
2641 "uniform float4x4 ViewToLight,\n"
2642 "uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2643 "uniform float3 LightPosition,\n"
2644 "uniform half2 PixelToScreenTexCoord,\n"
2645 "uniform half3 DeferredColor_Ambient,\n"
2646 "uniform half3 DeferredColor_Diffuse,\n"
2647 "#ifdef USESPECULAR\n"
2648 "uniform half3 DeferredColor_Specular,\n"
2649 "uniform half SpecularPower,\n"
2650 "#endif\n"
2651 "uniform sampler2D Texture_Attenuation,\n"
2652 "uniform sampler2D Texture_ScreenDepth,\n"
2653 "uniform sampler2D Texture_ScreenNormalMap,\n"
2654 "\n"
2655 "#ifdef USECUBEFILTER\n"
2656 "uniform samplerCUBE Texture_Cube,\n"
2657 "#endif\n"
2658 "\n"
2659 "#ifdef USESHADOWMAPRECT\n"
2660 "# ifdef USESHADOWSAMPLER\n"
2661 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2662 "# else\n"
2663 "uniform samplerRECT Texture_ShadowMapRect,\n"
2664 "# endif\n"
2665 "#endif\n"
2666 "\n"
2667 "#ifdef USESHADOWMAP2D\n"
2668 "# ifdef USESHADOWSAMPLER\n"
2669 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2670 "# else\n"
2671 "uniform sampler2D Texture_ShadowMap2D,\n"
2672 "# endif\n"
2673 "#endif\n"
2674 "\n"
2675 "#ifdef USESHADOWMAPVSDCT\n"
2676 "uniform samplerCUBE Texture_CubeProjection,\n"
2677 "#endif\n"
2678 "\n"
2679 "#ifdef USESHADOWMAPCUBE\n"
2680 "# ifdef USESHADOWSAMPLER\n"
2681 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2682 "# else\n"
2683 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2684 "# endif\n"
2685 "#endif\n"
2686 "\n"
2687 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2688 "uniform float2 ShadowMap_TextureScale,\n"
2689 "uniform float4 ShadowMap_Parameters,\n"
2690 "#endif\n"
2691 "\n"
2692 "out float4 gl_FragData0 : COLOR0,\n"
2693 "out float4 gl_FragData1 : COLOR1\n"
2694 ")\n"
2695 "{\n"
2696 "       // calculate viewspace pixel position\n"
2697 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2698 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2699 "       float3 position;\n"
2700 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2701 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2702 "       // decode viewspace pixel normal\n"
2703 "       half4 normalmap = tex2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
2704 "       half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
2705 "       // surfacenormal = pixel normal in viewspace\n"
2706 "       // LightVector = pixel to light in viewspace\n"
2707 "       // CubeVector = position in lightspace\n"
2708 "       // eyevector = pixel to view in viewspace\n"
2709 "       float3 CubeVector = float3(mul(ViewToLight, float4(position,1)));\n"
2710 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2711 "#ifdef USEDIFFUSE\n"
2712 "       // calculate diffuse shading\n"
2713 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2714 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2715 "#endif\n"
2716 "#ifdef USESPECULAR\n"
2717 "       // calculate directional shading\n"
2718 "       float3 eyevector = position * -1.0;\n"
2719 "#  ifdef USEEXACTSPECULARMATH\n"
2720 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
2721 "#  else\n"
2722 "       half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
2723 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
2724 "#  endif\n"
2725 "#endif\n"
2726 "\n"
2727 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2728 "       fade *= ShadowMapCompare(CubeVector,\n"
2729 "# if defined(USESHADOWMAP2D)\n"
2730 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2731 "# endif\n"
2732 "# if defined(USESHADOWMAPRECT)\n"
2733 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2734 "# endif\n"
2735 "# if defined(USESHADOWMAPCUBE)\n"
2736 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2737 "# endif\n"
2738 "\n"
2739 "#ifdef USESHADOWMAPVSDCT\n"
2740 ", Texture_CubeProjection\n"
2741 "#endif\n"
2742 "       );\n"
2743 "#endif\n"
2744 "\n"
2745 "#ifdef USEDIFFUSE\n"
2746 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2747 "#else\n"
2748 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2749 "#endif\n"
2750 "#ifdef USESPECULAR\n"
2751 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2752 "#else\n"
2753 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2754 "#endif\n"
2755 "\n"
2756 "# ifdef USECUBEFILTER\n"
2757 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2758 "       gl_FragData0.rgb *= cubecolor;\n"
2759 "       gl_FragData1.rgb *= cubecolor;\n"
2760 "# endif\n"
2761 "}\n"
2762 "#endif // FRAGMENT_SHADER\n"
2763 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2764 "\n"
2765 "\n"
2766 "\n"
2767 "\n"
2768 "#ifdef VERTEX_SHADER\n"
2769 "void main\n"
2770 "(\n"
2771 "float4 gl_Vertex : POSITION,\n"
2772 "uniform float4x4 ModelViewProjectionMatrix,\n"
2773 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2774 "float4 gl_Color : COLOR0,\n"
2775 "#endif\n"
2776 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2777 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2778 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2779 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2780 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2781 "\n"
2782 "uniform float3 EyePosition,\n"
2783 "uniform float4x4 TexMatrix,\n"
2784 "#ifdef USEVERTEXTEXTUREBLEND\n"
2785 "uniform float4x4 BackgroundTexMatrix,\n"
2786 "#endif\n"
2787 "#ifdef MODE_LIGHTSOURCE\n"
2788 "uniform float4x4 ModelToLight,\n"
2789 "#endif\n"
2790 "#ifdef MODE_LIGHTSOURCE\n"
2791 "uniform float3 LightPosition,\n"
2792 "#endif\n"
2793 "#ifdef MODE_LIGHTDIRECTION\n"
2794 "uniform float3 LightDir,\n"
2795 "#endif\n"
2796 "uniform float4 FogPlane,\n"
2797 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2798 "uniform float3 LightPosition,\n"
2799 "#endif\n"
2800 "#ifdef USESHADOWMAPORTHO\n"
2801 "uniform float4x4 ShadowMapMatrix,\n"
2802 "#endif\n"
2803 "\n"
2804 "out float4 gl_FrontColor : COLOR,\n"
2805 "out float4 TexCoordBoth : TEXCOORD0,\n"
2806 "#ifdef USELIGHTMAP\n"
2807 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2808 "#endif\n"
2809 "#ifdef USEEYEVECTOR\n"
2810 "out float3 EyeVector : TEXCOORD2,\n"
2811 "#endif\n"
2812 "#ifdef USEREFLECTION\n"
2813 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2814 "#endif\n"
2815 "#ifdef USEFOG\n"
2816 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2817 "#endif\n"
2818 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2819 "out float3 LightVector : TEXCOORD1,\n"
2820 "#endif\n"
2821 "#ifdef MODE_LIGHTSOURCE\n"
2822 "out float3 CubeVector : TEXCOORD3,\n"
2823 "#endif\n"
2824 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2825 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2826 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2827 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2828 "#endif\n"
2829 "#ifdef USESHADOWMAPORTHO\n"
2830 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2831 "#endif\n"
2832 "out float4 gl_Position : POSITION\n"
2833 ")\n"
2834 "{\n"
2835 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2836 "       gl_FrontColor = gl_Color;\n"
2837 "#endif\n"
2838 "       // copy the surface texcoord\n"
2839 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2840 "#ifdef USEVERTEXTEXTUREBLEND\n"
2841 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2842 "#endif\n"
2843 "#ifdef USELIGHTMAP\n"
2844 "       TexCoordLightmap = float2(gl_MultiTexCoord4);\n"
2845 "#endif\n"
2846 "\n"
2847 "#ifdef MODE_LIGHTSOURCE\n"
2848 "       // transform vertex position into light attenuation/cubemap space\n"
2849 "       // (-1 to +1 across the light box)\n"
2850 "       CubeVector = float3(mul(ModelToLight, gl_Vertex));\n"
2851 "\n"
2852 "# ifdef USEDIFFUSE\n"
2853 "       // transform unnormalized light direction into tangent space\n"
2854 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2855 "       //  normalize it per pixel)\n"
2856 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2857 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2858 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2859 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2860 "# endif\n"
2861 "#endif\n"
2862 "\n"
2863 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2864 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2865 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2866 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2867 "#endif\n"
2868 "\n"
2869 "       // transform unnormalized eye direction into tangent space\n"
2870 "#ifdef USEEYEVECTOR\n"
2871 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2872 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2873 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2874 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2875 "#endif\n"
2876 "\n"
2877 "#ifdef USEFOG\n"
2878 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2879 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2880 "#endif\n"
2881 "\n"
2882 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2883 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2884 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2885 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2886 "#endif\n"
2887 "\n"
2888 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2889 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2890 "\n"
2891 "#ifdef USESHADOWMAPORTHO\n"
2892 "       ShadowMapTC = float3(mul(ShadowMapMatrix, gl_Position));\n"
2893 "#endif\n"
2894 "\n"
2895 "#ifdef USEREFLECTION\n"
2896 "       ModelViewProjectionPosition = gl_Position;\n"
2897 "#endif\n"
2898 "}\n"
2899 "#endif // VERTEX_SHADER\n"
2900 "\n"
2901 "\n"
2902 "\n"
2903 "\n"
2904 "#ifdef FRAGMENT_SHADER\n"
2905 "void main\n"
2906 "(\n"
2907 "#ifdef USEDEFERREDLIGHTMAP\n"
2908 "float2 Pixel : WPOS,\n"
2909 "#endif\n"
2910 "float4 gl_FrontColor : COLOR,\n"
2911 "float4 TexCoordBoth : TEXCOORD0,\n"
2912 "#ifdef USELIGHTMAP\n"
2913 "float2 TexCoordLightmap : TEXCOORD1,\n"
2914 "#endif\n"
2915 "#ifdef USEEYEVECTOR\n"
2916 "float3 EyeVector : TEXCOORD2,\n"
2917 "#endif\n"
2918 "#ifdef USEREFLECTION\n"
2919 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2920 "#endif\n"
2921 "#ifdef USEFOG\n"
2922 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2923 "#endif\n"
2924 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2925 "float3 LightVector : TEXCOORD1,\n"
2926 "#endif\n"
2927 "#ifdef MODE_LIGHTSOURCE\n"
2928 "float3 CubeVector : TEXCOORD3,\n"
2929 "#endif\n"
2930 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2931 "float4 ModelViewPosition : TEXCOORD0,\n"
2932 "#endif\n"
2933 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2934 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2935 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2936 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2937 "#endif\n"
2938 "#ifdef USESHADOWMAPORTHO\n"
2939 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2940 "#endif\n"
2941 "\n"
2942 "uniform sampler2D Texture_Normal,\n"
2943 "uniform sampler2D Texture_Color,\n"
2944 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2945 "uniform sampler2D Texture_Gloss,\n"
2946 "#endif\n"
2947 "#ifdef USEGLOW\n"
2948 "uniform sampler2D Texture_Glow,\n"
2949 "#endif\n"
2950 "#ifdef USEVERTEXTEXTUREBLEND\n"
2951 "uniform sampler2D Texture_SecondaryNormal,\n"
2952 "uniform sampler2D Texture_SecondaryColor,\n"
2953 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2954 "uniform sampler2D Texture_SecondaryGloss,\n"
2955 "#endif\n"
2956 "#ifdef USEGLOW\n"
2957 "uniform sampler2D Texture_SecondaryGlow,\n"
2958 "#endif\n"
2959 "#endif\n"
2960 "#ifdef USECOLORMAPPING\n"
2961 "uniform sampler2D Texture_Pants,\n"
2962 "uniform sampler2D Texture_Shirt,\n"
2963 "#endif\n"
2964 "#ifdef USEFOG\n"
2965 "uniform sampler2D Texture_FogHeightTexture,\n"
2966 "uniform sampler2D Texture_FogMask,\n"
2967 "#endif\n"
2968 "#ifdef USELIGHTMAP\n"
2969 "uniform sampler2D Texture_Lightmap,\n"
2970 "#endif\n"
2971 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2972 "uniform sampler2D Texture_Deluxemap,\n"
2973 "#endif\n"
2974 "#ifdef USEREFLECTION\n"
2975 "uniform sampler2D Texture_Reflection,\n"
2976 "#endif\n"
2977 "\n"
2978 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2979 "uniform sampler2D Texture_ScreenDepth,\n"
2980 "uniform sampler2D Texture_ScreenNormalMap,\n"
2981 "#endif\n"
2982 "#ifdef USEDEFERREDLIGHTMAP\n"
2983 "uniform sampler2D Texture_ScreenDiffuse,\n"
2984 "uniform sampler2D Texture_ScreenSpecular,\n"
2985 "#endif\n"
2986 "\n"
2987 "#ifdef USECOLORMAPPING\n"
2988 "uniform half3 Color_Pants,\n"
2989 "uniform half3 Color_Shirt,\n"
2990 "#endif\n"
2991 "#ifdef USEFOG\n"
2992 "uniform float3 FogColor,\n"
2993 "uniform float FogRangeRecip,\n"
2994 "uniform float FogPlaneViewDist,\n"
2995 "uniform float FogHeightFade,\n"
2996 "#endif\n"
2997 "\n"
2998 "#ifdef USEOFFSETMAPPING\n"
2999 "uniform float OffsetMapping_Scale,\n"
3000 "#endif\n"
3001 "\n"
3002 "#ifdef USEDEFERREDLIGHTMAP\n"
3003 "uniform half2 PixelToScreenTexCoord,\n"
3004 "uniform half3 DeferredMod_Diffuse,\n"
3005 "uniform half3 DeferredMod_Specular,\n"
3006 "#endif\n"
3007 "uniform half3 Color_Ambient,\n"
3008 "uniform half3 Color_Diffuse,\n"
3009 "uniform half3 Color_Specular,\n"
3010 "uniform half SpecularPower,\n"
3011 "#ifdef USEGLOW\n"
3012 "uniform half3 Color_Glow,\n"
3013 "#endif\n"
3014 "uniform half Alpha,\n"
3015 "#ifdef USEREFLECTION\n"
3016 "uniform float4 DistortScaleRefractReflect,\n"
3017 "uniform float4 ScreenScaleRefractReflect,\n"
3018 "uniform float4 ScreenCenterRefractReflect,\n"
3019 "uniform half4 ReflectColor,\n"
3020 "#endif\n"
3021 "#ifdef USEREFLECTCUBE\n"
3022 "uniform float4x4 ModelToReflectCube,\n"
3023 "uniform sampler2D Texture_ReflectMask,\n"
3024 "uniform samplerCUBE Texture_ReflectCube,\n"
3025 "#endif\n"
3026 "#ifdef MODE_LIGHTDIRECTION\n"
3027 "uniform half3 LightColor,\n"
3028 "#endif\n"
3029 "#ifdef MODE_LIGHTSOURCE\n"
3030 "uniform half3 LightColor,\n"
3031 "#endif\n"
3032 "\n"
3033 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3034 "uniform sampler2D Texture_Attenuation,\n"
3035 "uniform samplerCUBE Texture_Cube,\n"
3036 "#endif\n"
3037 "\n"
3038 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3039 "\n"
3040 "#ifdef USESHADOWMAPRECT\n"
3041 "# ifdef USESHADOWSAMPLER\n"
3042 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
3043 "# else\n"
3044 "uniform samplerRECT Texture_ShadowMapRect,\n"
3045 "# endif\n"
3046 "#endif\n"
3047 "\n"
3048 "#ifdef USESHADOWMAP2D\n"
3049 "# ifdef USESHADOWSAMPLER\n"
3050 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
3051 "# else\n"
3052 "uniform sampler2D Texture_ShadowMap2D,\n"
3053 "# endif\n"
3054 "#endif\n"
3055 "\n"
3056 "#ifdef USESHADOWMAPVSDCT\n"
3057 "uniform samplerCUBE Texture_CubeProjection,\n"
3058 "#endif\n"
3059 "\n"
3060 "#ifdef USESHADOWMAPCUBE\n"
3061 "# ifdef USESHADOWSAMPLER\n"
3062 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
3063 "# else\n"
3064 "uniform samplerCUBE Texture_ShadowMapCube,\n"
3065 "# endif\n"
3066 "#endif\n"
3067 "\n"
3068 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
3069 "uniform float2 ShadowMap_TextureScale,\n"
3070 "uniform float4 ShadowMap_Parameters,\n"
3071 "#endif\n"
3072 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3073 "\n"
3074 "out float4 gl_FragColor : COLOR\n"
3075 ")\n"
3076 "{\n"
3077 "       float2 TexCoord = TexCoordBoth.xy;\n"
3078 "#ifdef USEVERTEXTEXTUREBLEND\n"
3079 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
3080 "#endif\n"
3081 "#ifdef USEOFFSETMAPPING\n"
3082 "       // apply offsetmapping\n"
3083 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3084 "#define TexCoord TexCoordOffset\n"
3085 "#endif\n"
3086 "\n"
3087 "       // combine the diffuse textures (base, pants, shirt)\n"
3088 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3089 "#ifdef USEALPHAKILL\n"
3090 "       if (color.a < 0.5)\n"
3091 "               discard;\n"
3092 "#endif\n"
3093 "       color.a *= Alpha;\n"
3094 "#ifdef USECOLORMAPPING\n"
3095 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord)) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
3096 "#endif\n"
3097 "#ifdef USEVERTEXTEXTUREBLEND\n"
3098 "       float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3099 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3100 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3101 "       color.rgb = half3(lerp(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
3102 "       color.a = 1.0;\n"
3103 "       //color = lerp(half4(1, 0, 0, 1), color, terrainblend);\n"
3104 "#endif\n"
3105 "\n"
3106 "       // get the surface normal\n"
3107 "#ifdef USEVERTEXTEXTUREBLEND\n"
3108 "       half3 surfacenormal = normalize(half3(lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3109 "#else\n"
3110 "       half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
3111 "#endif\n"
3112 "\n"
3113 "       // get the material colors\n"
3114 "       half3 diffusetex = color.rgb;\n"
3115 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3116 "# ifdef USEVERTEXTEXTUREBLEND\n"
3117 "       half4 glosstex = half4(lerp(float4(tex2D(Texture_SecondaryGloss, TexCoord2)), float4(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
3118 "# else\n"
3119 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3120 "# endif\n"
3121 "#endif\n"
3122 "\n"
3123 "#ifdef USEREFLECTCUBE\n"
3124 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3125 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3126 "       float3 ReflectCubeTexCoord = float3(mul(ModelToReflectCube, float4(ModelReflectVector, 0)));\n"
3127 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord)) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord));\n"
3128 "#endif\n"
3129 "\n"
3130 "\n"
3131 "\n"
3132 "\n"
3133 "#ifdef MODE_LIGHTSOURCE\n"
3134 "       // light source\n"
3135 "#ifdef USEDIFFUSE\n"
3136 "       half3 lightnormal = half3(normalize(LightVector));\n"
3137 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3138 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3139 "#ifdef USESPECULAR\n"
3140 "#ifdef USEEXACTSPECULARMATH\n"
3141 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
3142 "#else\n"
3143 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3144 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
3145 "#endif\n"
3146 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3147 "#endif\n"
3148 "#else\n"
3149 "       color.rgb = diffusetex * Color_Ambient;\n"
3150 "#endif\n"
3151 "       color.rgb *= LightColor;\n"
3152 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
3153 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
3154 "       color.rgb *= ShadowMapCompare(CubeVector,\n"
3155 "# if defined(USESHADOWMAP2D)\n"
3156 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3157 "# endif\n"
3158 "# if defined(USESHADOWMAPRECT)\n"
3159 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3160 "# endif\n"
3161 "# if defined(USESHADOWMAPCUBE)\n"
3162 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
3163 "# endif\n"
3164 "\n"
3165 "#ifdef USESHADOWMAPVSDCT\n"
3166 ", Texture_CubeProjection\n"
3167 "#endif\n"
3168 "       );\n"
3169 "\n"
3170 "#endif\n"
3171 "# ifdef USECUBEFILTER\n"
3172 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector));\n"
3173 "# endif\n"
3174 "#endif // MODE_LIGHTSOURCE\n"
3175 "\n"
3176 "\n"
3177 "\n"
3178 "\n"
3179 "#ifdef MODE_LIGHTDIRECTION\n"
3180 "#define SHADING\n"
3181 "#ifdef USEDIFFUSE\n"
3182 "       half3 lightnormal = half3(normalize(LightVector));\n"
3183 "#endif\n"
3184 "#define lightcolor LightColor\n"
3185 "#endif // MODE_LIGHTDIRECTION\n"
3186 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3187 "#define SHADING\n"
3188 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3189 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3190 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3191 "       // convert modelspace light vector to tangentspace\n"
3192 "       half3 lightnormal;\n"
3193 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3194 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3195 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3196 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3197 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3198 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3199 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3200 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3201 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3202 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3203 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3204 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3205 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3206 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3207 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3208 "#define SHADING\n"
3209 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3210 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3211 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3212 "#endif\n"
3213 "\n"
3214 "\n"
3215 "\n"
3216 "\n"
3217 "#ifdef MODE_LIGHTMAP\n"
3218 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
3219 "#endif // MODE_LIGHTMAP\n"
3220 "#ifdef MODE_VERTEXCOLOR\n"
3221 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3222 "#endif // MODE_VERTEXCOLOR\n"
3223 "#ifdef MODE_FLATCOLOR\n"
3224 "       color.rgb = diffusetex * Color_Ambient;\n"
3225 "#endif // MODE_FLATCOLOR\n"
3226 "\n"
3227 "\n"
3228 "\n"
3229 "\n"
3230 "#ifdef SHADING\n"
3231 "# ifdef USEDIFFUSE\n"
3232 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3233 "#  ifdef USESPECULAR\n"
3234 "#   ifdef USEEXACTSPECULARMATH\n"
3235 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
3236 "#   else\n"
3237 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3238 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
3239 "#   endif\n"
3240 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3241 "#  else\n"
3242 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3243 "#  endif\n"
3244 "# else\n"
3245 "       color.rgb = diffusetex * Color_Ambient;\n"
3246 "# endif\n"
3247 "#endif\n"
3248 "\n"
3249 "#ifdef USESHADOWMAPORTHO\n"
3250 "       color.rgb *= ShadowMapCompare(ShadowMapTC,\n"
3251 "# if defined(USESHADOWMAP2D)\n"
3252 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3253 "# endif\n"
3254 "# if defined(USESHADOWMAPRECT)\n"
3255 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3256 "# endif\n"
3257 "       );\n"
3258 "#endif\n"
3259 "\n"
3260 "#ifdef USEDEFERREDLIGHTMAP\n"
3261 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3262 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
3263 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
3264 "#endif\n"
3265 "\n"
3266 "#ifdef USEGLOW\n"
3267 "#ifdef USEVERTEXTEXTUREBLEND\n"
3268 "       color.rgb += lerp(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
3269 "#else\n"
3270 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
3271 "#endif\n"
3272 "#endif\n"
3273 "\n"
3274 "#ifdef USEFOG\n"
3275 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3276 "#endif\n"
3277 "\n"
3278 "       // 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"
3279 "#ifdef USEREFLECTION\n"
3280 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3281 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3282 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3283 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
3284 "       // FIXME temporary hack to detect the case that the reflection\n"
3285 "       // gets blackened at edges due to leaving the area that contains actual\n"
3286 "       // content.\n"
3287 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3288 "       // 'appening.\n"
3289 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3290 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3291 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3292 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3293 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3294 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
3295 "#endif\n"
3296 "\n"
3297 "       gl_FragColor = float4(color);\n"
3298 "}\n"
3299 "#endif // FRAGMENT_SHADER\n"
3300 "\n"
3301 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3302 "#endif // !MODE_DEFERREDGEOMETRY\n"
3303 "#endif // !MODE_WATER\n"
3304 "#endif // !MODE_REFRACTION\n"
3305 "#endif // !MODE_BLOOMBLUR\n"
3306 "#endif // !MODE_GENERIC\n"
3307 "#endif // !MODE_POSTPROCESS\n"
3308 "#endif // !MODE_SHOWDEPTH\n"
3309 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3310 ;
3311
3312 char *glslshaderstring = NULL;
3313 char *cgshaderstring = NULL;
3314
3315 //=======================================================================================================================================================
3316
3317 typedef struct shaderpermutationinfo_s
3318 {
3319         const char *pretext;
3320         const char *name;
3321 }
3322 shaderpermutationinfo_t;
3323
3324 typedef struct shadermodeinfo_s
3325 {
3326         const char *vertexfilename;
3327         const char *geometryfilename;
3328         const char *fragmentfilename;
3329         const char *pretext;
3330         const char *name;
3331 }
3332 shadermodeinfo_t;
3333
3334 typedef enum shaderpermutation_e
3335 {
3336         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3337         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3338         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3339         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3340         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3341         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3342         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3343         SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3344         SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3345         SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3346         SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3347         SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3348         SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3349         SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3350         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<14, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3351         SHADERPERMUTATION_REFLECTION = 1<<15, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3352         SHADERPERMUTATION_OFFSETMAPPING = 1<<16, ///< adjust texcoords to roughly simulate a displacement mapped surface
3353         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<17, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3354         SHADERPERMUTATION_SHADOWMAPRECT = 1<<18, ///< (lightsource) use shadowmap rectangle texture as light filter
3355         SHADERPERMUTATION_SHADOWMAPCUBE = 1<<19, ///< (lightsource) use shadowmap cubemap texture as light filter
3356         SHADERPERMUTATION_SHADOWMAP2D = 1<<20, ///< (lightsource) use shadowmap rectangle texture as light filter
3357         SHADERPERMUTATION_SHADOWMAPPCF = 1<<21, ///< (lightsource) use percentage closer filtering on shadowmap test results
3358         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<22, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3359         SHADERPERMUTATION_SHADOWSAMPLER = 1<<23, ///< (lightsource) use hardware shadowmap test
3360         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<24, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3361         SHADERPERMUTATION_SHADOWMAPORTHO = 1<<25, //< (lightsource) use orthographic shadowmap projection
3362         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<26, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3363         SHADERPERMUTATION_ALPHAKILL = 1<<27, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3364         SHADERPERMUTATION_REFLECTCUBE = 1<<28, ///< fake reflections using global cubemap (not HDRI light probe)
3365         SHADERPERMUTATION_LIMIT = 1<<29, ///< size of permutations array
3366         SHADERPERMUTATION_COUNT = 29 ///< size of shaderpermutationinfo array
3367 }
3368 shaderpermutation_t;
3369
3370 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3371 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3372 {
3373         {"#define USEDIFFUSE\n", " diffuse"},
3374         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3375         {"#define USEVIEWTINT\n", " viewtint"},
3376         {"#define USECOLORMAPPING\n", " colormapping"},
3377         {"#define USESATURATION\n", " saturation"},
3378         {"#define USEFOGINSIDE\n", " foginside"},
3379         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3380         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3381         {"#define USEGAMMARAMPS\n", " gammaramps"},
3382         {"#define USECUBEFILTER\n", " cubefilter"},
3383         {"#define USEGLOW\n", " glow"},
3384         {"#define USEBLOOM\n", " bloom"},
3385         {"#define USESPECULAR\n", " specular"},
3386         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3387         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3388         {"#define USEREFLECTION\n", " reflection"},
3389         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3390         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3391         {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3392         {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3393         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3394         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3395         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3396         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3397         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3398         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3399         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3400         {"#define USEALPHAKILL\n", " alphakill"},
3401         {"#define USEREFLECTCUBE\n", " reflectcube"},
3402 };
3403
3404 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3405 typedef enum shadermode_e
3406 {
3407         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3408         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3409         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3410         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3411         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3412         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3413         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3414         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3415         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3416         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3417         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3418         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3419         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3420         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3421         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3422         SHADERMODE_COUNT
3423 }
3424 shadermode_t;
3425
3426 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3427 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3428 {
3429         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3430         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3431         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3432         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3433         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3434         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3435         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3436         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3437         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3438         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3439         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3440         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3441         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3442         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3443         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3444 };
3445
3446 #ifdef SUPPORTCG
3447 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3448 {
3449         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3450         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3451         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3452         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3453         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3454         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3455         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3456         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3457         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3458         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3459         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3460         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3461         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3462         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3463         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3464 };
3465 #endif
3466
3467 struct r_glsl_permutation_s;
3468 typedef struct r_glsl_permutation_s
3469 {
3470         /// hash lookup data
3471         struct r_glsl_permutation_s *hashnext;
3472         unsigned int mode;
3473         unsigned int permutation;
3474
3475         /// indicates if we have tried compiling this permutation already
3476         qboolean compiled;
3477         /// 0 if compilation failed
3478         int program;
3479         /// locations of detected uniforms in program object, or -1 if not found
3480         int loc_Texture_First;
3481         int loc_Texture_Second;
3482         int loc_Texture_GammaRamps;
3483         int loc_Texture_Normal;
3484         int loc_Texture_Color;
3485         int loc_Texture_Gloss;
3486         int loc_Texture_Glow;
3487         int loc_Texture_SecondaryNormal;
3488         int loc_Texture_SecondaryColor;
3489         int loc_Texture_SecondaryGloss;
3490         int loc_Texture_SecondaryGlow;
3491         int loc_Texture_Pants;
3492         int loc_Texture_Shirt;
3493         int loc_Texture_FogHeightTexture;
3494         int loc_Texture_FogMask;
3495         int loc_Texture_Lightmap;
3496         int loc_Texture_Deluxemap;
3497         int loc_Texture_Attenuation;
3498         int loc_Texture_Cube;
3499         int loc_Texture_Refraction;
3500         int loc_Texture_Reflection;
3501         int loc_Texture_ShadowMapRect;
3502         int loc_Texture_ShadowMapCube;
3503         int loc_Texture_ShadowMap2D;
3504         int loc_Texture_CubeProjection;
3505         int loc_Texture_ScreenDepth;
3506         int loc_Texture_ScreenNormalMap;
3507         int loc_Texture_ScreenDiffuse;
3508         int loc_Texture_ScreenSpecular;
3509         int loc_Texture_ReflectMask;
3510         int loc_Texture_ReflectCube;
3511         int loc_Alpha;
3512         int loc_BloomBlur_Parameters;
3513         int loc_ClientTime;
3514         int loc_Color_Ambient;
3515         int loc_Color_Diffuse;
3516         int loc_Color_Specular;
3517         int loc_Color_Glow;
3518         int loc_Color_Pants;
3519         int loc_Color_Shirt;
3520         int loc_DeferredColor_Ambient;
3521         int loc_DeferredColor_Diffuse;
3522         int loc_DeferredColor_Specular;
3523         int loc_DeferredMod_Diffuse;
3524         int loc_DeferredMod_Specular;
3525         int loc_DistortScaleRefractReflect;
3526         int loc_EyePosition;
3527         int loc_FogColor;
3528         int loc_FogHeightFade;
3529         int loc_FogPlane;
3530         int loc_FogPlaneViewDist;
3531         int loc_FogRangeRecip;
3532         int loc_LightColor;
3533         int loc_LightDir;
3534         int loc_LightPosition;
3535         int loc_OffsetMapping_Scale;
3536         int loc_PixelSize;
3537         int loc_ReflectColor;
3538         int loc_ReflectFactor;
3539         int loc_ReflectOffset;
3540         int loc_RefractColor;
3541         int loc_Saturation;
3542         int loc_ScreenCenterRefractReflect;
3543         int loc_ScreenScaleRefractReflect;
3544         int loc_ScreenToDepth;
3545         int loc_ShadowMap_Parameters;
3546         int loc_ShadowMap_TextureScale;
3547         int loc_SpecularPower;
3548         int loc_UserVec1;
3549         int loc_UserVec2;
3550         int loc_UserVec3;
3551         int loc_UserVec4;
3552         int loc_ViewTintColor;
3553         int loc_ViewToLight;
3554         int loc_ModelToLight;
3555         int loc_TexMatrix;
3556         int loc_BackgroundTexMatrix;
3557         int loc_ModelViewProjectionMatrix;
3558         int loc_ModelViewMatrix;
3559         int loc_PixelToScreenTexCoord;
3560         int loc_ModelToReflectCube;
3561         int loc_ShadowMapMatrix;        
3562 }
3563 r_glsl_permutation_t;
3564
3565 #define SHADERPERMUTATION_HASHSIZE 256
3566
3567 /// information about each possible shader permutation
3568 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3569 /// currently selected permutation
3570 r_glsl_permutation_t *r_glsl_permutation;
3571 /// storage for permutations linked in the hash table
3572 memexpandablearray_t r_glsl_permutationarray;
3573
3574 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3575 {
3576         //unsigned int hashdepth = 0;
3577         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3578         r_glsl_permutation_t *p;
3579         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3580         {
3581                 if (p->mode == mode && p->permutation == permutation)
3582                 {
3583                         //if (hashdepth > 10)
3584                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3585                         return p;
3586                 }
3587                 //hashdepth++;
3588         }
3589         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3590         p->mode = mode;
3591         p->permutation = permutation;
3592         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3593         r_glsl_permutationhash[mode][hashindex] = p;
3594         //if (hashdepth > 10)
3595         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3596         return p;
3597 }
3598
3599 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3600 {
3601         char *shaderstring;
3602         if (!filename || !filename[0])
3603                 return NULL;
3604         if (!strcmp(filename, "glsl/default.glsl"))
3605         {
3606                 if (!glslshaderstring)
3607                 {
3608                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3609                         if (glslshaderstring)
3610                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3611                         else
3612                                 glslshaderstring = (char *)builtinshaderstring;
3613                 }
3614                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3615                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3616                 return shaderstring;
3617         }
3618         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3619         if (shaderstring)
3620         {
3621                 if (printfromdisknotice)
3622                         Con_DPrintf("from disk %s... ", filename);
3623                 return shaderstring;
3624         }
3625         return shaderstring;
3626 }
3627
3628 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3629 {
3630         int i;
3631         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3632         int vertstrings_count = 0;
3633         int geomstrings_count = 0;
3634         int fragstrings_count = 0;
3635         char *vertexstring, *geometrystring, *fragmentstring;
3636         const char *vertstrings_list[32+3];
3637         const char *geomstrings_list[32+3];
3638         const char *fragstrings_list[32+3];
3639         char permutationname[256];
3640
3641         if (p->compiled)
3642                 return;
3643         p->compiled = true;
3644         p->program = 0;
3645
3646         permutationname[0] = 0;
3647         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3648         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3649         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3650
3651         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3652
3653         // the first pretext is which type of shader to compile as
3654         // (later these will all be bound together as a program object)
3655         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3656         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3657         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3658
3659         // the second pretext is the mode (for example a light source)
3660         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3661         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3662         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3663         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3664
3665         // now add all the permutation pretexts
3666         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3667         {
3668                 if (permutation & (1<<i))
3669                 {
3670                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3671                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3672                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3673                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3674                 }
3675                 else
3676                 {
3677                         // keep line numbers correct
3678                         vertstrings_list[vertstrings_count++] = "\n";
3679                         geomstrings_list[geomstrings_count++] = "\n";
3680                         fragstrings_list[fragstrings_count++] = "\n";
3681                 }
3682         }
3683
3684         // now append the shader text itself
3685         vertstrings_list[vertstrings_count++] = vertexstring;
3686         geomstrings_list[geomstrings_count++] = geometrystring;
3687         fragstrings_list[fragstrings_count++] = fragmentstring;
3688
3689         // if any sources were NULL, clear the respective list
3690         if (!vertexstring)
3691                 vertstrings_count = 0;
3692         if (!geometrystring)
3693                 geomstrings_count = 0;
3694         if (!fragmentstring)
3695                 fragstrings_count = 0;
3696
3697         // compile the shader program
3698         if (vertstrings_count + geomstrings_count + fragstrings_count)
3699                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3700         if (p->program)
3701         {
3702                 CHECKGLERROR
3703                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3704                 // look up all the uniform variable names we care about, so we don't
3705                 // have to look them up every time we set them
3706
3707                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3708                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3709                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3710                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3711                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3712                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3713                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3714                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3715                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3716                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3717                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3718                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3719                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3720                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3721                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3722                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3723                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3724                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3725                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3726                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3727                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3728                 p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3729                 p->loc_Texture_ShadowMapCube      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3730                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3731                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3732                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3733                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3734                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3735                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3736                 p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3737                 p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3738                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3739                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3740                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3741                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3742                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3743                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3744                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3745                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3746                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3747                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3748                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3749                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3750                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3751                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3752                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3753                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3754                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3755                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3756                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3757                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3758                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3759                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3760                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3761                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3762                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3763                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3764                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3765                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3766                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3767                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3768                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3769                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3770                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3771                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3772                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3773                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3774                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3775                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3776                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3777                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3778                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3779                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3780                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3781                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3782                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3783                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3784                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3785                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3786                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3787                 p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3788                 p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");            
3789                 // initialize the samplers to refer to the texture units we use
3790                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3791                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3792                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3793                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3794                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3795                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3796                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3797                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3798                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3799                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3800                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3801                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3802                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3803                 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3804                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3805                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3806                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3807                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3808                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3809                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3810                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3811                 if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT);
3812                 if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
3813                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D);
3814                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3815                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3816                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3817                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3818                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3819                 if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
3820                 if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
3821                 CHECKGLERROR
3822                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3823         }
3824         else
3825                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3826
3827         // free the strings
3828         if (vertexstring)
3829                 Mem_Free(vertexstring);
3830         if (geometrystring)
3831                 Mem_Free(geometrystring);
3832         if (fragmentstring)
3833                 Mem_Free(fragmentstring);
3834 }
3835
3836 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3837 {
3838         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3839         if (r_glsl_permutation != perm)
3840         {
3841                 r_glsl_permutation = perm;
3842                 if (!r_glsl_permutation->program)
3843                 {
3844                         if (!r_glsl_permutation->compiled)
3845                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3846                         if (!r_glsl_permutation->program)
3847                         {
3848                                 // remove features until we find a valid permutation
3849                                 int i;
3850                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3851                                 {
3852                                         // reduce i more quickly whenever it would not remove any bits
3853                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3854                                         if (!(permutation & j))
3855                                                 continue;
3856                                         permutation -= j;
3857                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3858                                         if (!r_glsl_permutation->compiled)
3859                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3860                                         if (r_glsl_permutation->program)
3861                                                 break;
3862                                 }
3863                                 if (i >= SHADERPERMUTATION_COUNT)
3864                                 {
3865                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3866                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3867                                         qglUseProgramObjectARB(0);CHECKGLERROR
3868                                         return; // no bit left to clear, entire mode is broken
3869                                 }
3870                         }
3871                 }
3872                 CHECKGLERROR
3873                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3874         }
3875         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3876         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3877         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3878 }
3879
3880 #ifdef SUPPORTCG
3881 #include <Cg/cgGL.h>
3882 struct r_cg_permutation_s;
3883 typedef struct r_cg_permutation_s
3884 {
3885         /// hash lookup data
3886         struct r_cg_permutation_s *hashnext;
3887         unsigned int mode;
3888         unsigned int permutation;
3889
3890         /// indicates if we have tried compiling this permutation already
3891         qboolean compiled;
3892         /// 0 if compilation failed
3893         CGprogram vprogram;
3894         CGprogram fprogram;
3895         /// locations of detected parameters in programs, or NULL if not found
3896         CGparameter vp_EyePosition;
3897         CGparameter vp_FogPlane;
3898         CGparameter vp_LightDir;
3899         CGparameter vp_LightPosition;
3900         CGparameter vp_ModelToLight;
3901         CGparameter vp_TexMatrix;
3902         CGparameter vp_BackgroundTexMatrix;
3903         CGparameter vp_ModelViewProjectionMatrix;
3904         CGparameter vp_ModelViewMatrix;
3905         CGparameter vp_ShadowMapMatrix;
3906
3907         CGparameter fp_Texture_First;
3908         CGparameter fp_Texture_Second;
3909         CGparameter fp_Texture_GammaRamps;
3910         CGparameter fp_Texture_Normal;
3911         CGparameter fp_Texture_Color;
3912         CGparameter fp_Texture_Gloss;
3913         CGparameter fp_Texture_Glow;
3914         CGparameter fp_Texture_SecondaryNormal;
3915         CGparameter fp_Texture_SecondaryColor;
3916         CGparameter fp_Texture_SecondaryGloss;
3917         CGparameter fp_Texture_SecondaryGlow;
3918         CGparameter fp_Texture_Pants;
3919         CGparameter fp_Texture_Shirt;
3920         CGparameter fp_Texture_FogHeightTexture;
3921         CGparameter fp_Texture_FogMask;
3922         CGparameter fp_Texture_Lightmap;
3923         CGparameter fp_Texture_Deluxemap;
3924         CGparameter fp_Texture_Attenuation;
3925         CGparameter fp_Texture_Cube;
3926         CGparameter fp_Texture_Refraction;
3927         CGparameter fp_Texture_Reflection;
3928         CGparameter fp_Texture_ShadowMapRect;
3929         CGparameter fp_Texture_ShadowMapCube;
3930         CGparameter fp_Texture_ShadowMap2D;
3931         CGparameter fp_Texture_CubeProjection;
3932         CGparameter fp_Texture_ScreenDepth;
3933         CGparameter fp_Texture_ScreenNormalMap;
3934         CGparameter fp_Texture_ScreenDiffuse;
3935         CGparameter fp_Texture_ScreenSpecular;
3936         CGparameter fp_Texture_ReflectMask;
3937         CGparameter fp_Texture_ReflectCube;
3938         CGparameter fp_Alpha;
3939         CGparameter fp_BloomBlur_Parameters;
3940         CGparameter fp_ClientTime;
3941         CGparameter fp_Color_Ambient;
3942         CGparameter fp_Color_Diffuse;
3943         CGparameter fp_Color_Specular;
3944         CGparameter fp_Color_Glow;
3945         CGparameter fp_Color_Pants;
3946         CGparameter fp_Color_Shirt;
3947         CGparameter fp_DeferredColor_Ambient;
3948         CGparameter fp_DeferredColor_Diffuse;
3949         CGparameter fp_DeferredColor_Specular;
3950         CGparameter fp_DeferredMod_Diffuse;
3951         CGparameter fp_DeferredMod_Specular;
3952         CGparameter fp_DistortScaleRefractReflect;
3953         CGparameter fp_EyePosition;
3954         CGparameter fp_FogColor;
3955         CGparameter fp_FogHeightFade;
3956         CGparameter fp_FogPlane;
3957         CGparameter fp_FogPlaneViewDist;
3958         CGparameter fp_FogRangeRecip;
3959         CGparameter fp_LightColor;
3960         CGparameter fp_LightDir;
3961         CGparameter fp_LightPosition;
3962         CGparameter fp_OffsetMapping_Scale;
3963         CGparameter fp_PixelSize;
3964         CGparameter fp_ReflectColor;
3965         CGparameter fp_ReflectFactor;
3966         CGparameter fp_ReflectOffset;
3967         CGparameter fp_RefractColor;
3968         CGparameter fp_Saturation;
3969         CGparameter fp_ScreenCenterRefractReflect;
3970         CGparameter fp_ScreenScaleRefractReflect;
3971         CGparameter fp_ScreenToDepth;
3972         CGparameter fp_ShadowMap_Parameters;
3973         CGparameter fp_ShadowMap_TextureScale;
3974         CGparameter fp_SpecularPower;
3975         CGparameter fp_UserVec1;
3976         CGparameter fp_UserVec2;
3977         CGparameter fp_UserVec3;
3978         CGparameter fp_UserVec4;
3979         CGparameter fp_ViewTintColor;
3980         CGparameter fp_ViewToLight;
3981         CGparameter fp_PixelToScreenTexCoord;
3982         CGparameter fp_ModelToReflectCube;
3983 }
3984 r_cg_permutation_t;
3985
3986 /// information about each possible shader permutation
3987 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3988 /// currently selected permutation
3989 r_cg_permutation_t *r_cg_permutation;
3990 /// storage for permutations linked in the hash table
3991 memexpandablearray_t r_cg_permutationarray;
3992
3993 #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));}}
3994
3995 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3996 {
3997         //unsigned int hashdepth = 0;
3998         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3999         r_cg_permutation_t *p;
4000         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
4001         {
4002                 if (p->mode == mode && p->permutation == permutation)
4003                 {
4004                         //if (hashdepth > 10)
4005                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4006                         return p;
4007                 }
4008                 //hashdepth++;
4009         }
4010         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
4011         p->mode = mode;
4012         p->permutation = permutation;
4013         p->hashnext = r_cg_permutationhash[mode][hashindex];
4014         r_cg_permutationhash[mode][hashindex] = p;
4015         //if (hashdepth > 10)
4016         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4017         return p;
4018 }
4019
4020 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
4021 {
4022         char *shaderstring;
4023         if (!filename || !filename[0])
4024                 return NULL;
4025         if (!strcmp(filename, "cg/default.cg"))
4026         {
4027                 if (!cgshaderstring)
4028                 {
4029                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4030                         if (cgshaderstring)
4031                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4032                         else
4033                                 cgshaderstring = (char *)builtincgshaderstring;
4034                 }
4035                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4036                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4037                 return shaderstring;
4038         }
4039         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4040         if (shaderstring)
4041         {
4042                 if (printfromdisknotice)
4043                         Con_DPrintf("from disk %s... ", filename);
4044                 return shaderstring;
4045         }
4046         return shaderstring;
4047 }
4048
4049 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4050 {
4051         // TODO: load or create .fp and .vp shader files
4052 }
4053
4054 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4055 {
4056         int i;
4057         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4058         int vertstrings_count = 0, vertstring_length = 0;
4059         int geomstrings_count = 0, geomstring_length = 0;
4060         int fragstrings_count = 0, fragstring_length = 0;
4061         char *t;
4062         char *vertexstring, *geometrystring, *fragmentstring;
4063         char *vertstring, *geomstring, *fragstring;
4064         const char *vertstrings_list[32+3];
4065         const char *geomstrings_list[32+3];
4066         const char *fragstrings_list[32+3];
4067         char permutationname[256];
4068         char cachename[256];
4069         CGprofile vertexProfile;
4070         CGprofile fragmentProfile;
4071
4072         if (p->compiled)
4073                 return;
4074         p->compiled = true;
4075         p->vprogram = NULL;
4076         p->fprogram = NULL;
4077
4078         permutationname[0] = 0;
4079         cachename[0] = 0;
4080         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
4081         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4082         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4083
4084         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4085         strlcat(cachename, "cg/", sizeof(cachename));
4086
4087         // the first pretext is which type of shader to compile as
4088         // (later these will all be bound together as a program object)
4089         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4090         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4091         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4092
4093         // the second pretext is the mode (for example a light source)
4094         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4095         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4096         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4097         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4098         strlcat(cachename, modeinfo->name, sizeof(cachename));
4099
4100         // now add all the permutation pretexts
4101         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4102         {
4103                 if (permutation & (1<<i))
4104                 {
4105                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4106                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4107                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4108                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4109                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4110                 }
4111                 else
4112                 {
4113                         // keep line numbers correct
4114                         vertstrings_list[vertstrings_count++] = "\n";
4115                         geomstrings_list[geomstrings_count++] = "\n";
4116                         fragstrings_list[fragstrings_count++] = "\n";
4117                 }
4118         }
4119
4120         // replace spaces in the cachename with _ characters
4121         for (i = 0;cachename[i];i++)
4122                 if (cachename[i] == ' ')
4123                         cachename[i] = '_';
4124
4125         // now append the shader text itself
4126         vertstrings_list[vertstrings_count++] = vertexstring;
4127         geomstrings_list[geomstrings_count++] = geometrystring;
4128         fragstrings_list[fragstrings_count++] = fragmentstring;
4129
4130         // if any sources were NULL, clear the respective list
4131         if (!vertexstring)
4132                 vertstrings_count = 0;
4133         if (!geometrystring)
4134                 geomstrings_count = 0;
4135         if (!fragmentstring)
4136                 fragstrings_count = 0;
4137
4138         vertstring_length = 0;
4139         for (i = 0;i < vertstrings_count;i++)
4140                 vertstring_length += strlen(vertstrings_list[i]);
4141         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4142         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4143                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4144
4145         geomstring_length = 0;
4146         for (i = 0;i < geomstrings_count;i++)
4147                 geomstring_length += strlen(geomstrings_list[i]);
4148         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4149         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4150                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4151
4152         fragstring_length = 0;
4153         for (i = 0;i < fragstrings_count;i++)
4154                 fragstring_length += strlen(fragstrings_list[i]);
4155         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4156         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4157                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4158
4159         CHECKGLERROR
4160         CHECKCGERROR
4161         //vertexProfile = CG_PROFILE_ARBVP1;
4162         //fragmentProfile = CG_PROFILE_ARBFP1;
4163         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4164         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4165         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4166         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4167         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4168         CHECKGLERROR
4169
4170         // try to load the cached shader, or generate one
4171         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4172
4173         // if caching failed, do a dynamic compile for now
4174         CHECKCGERROR
4175         if (vertstring[0] && !p->vprogram)
4176                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4177         CHECKCGERROR
4178         if (fragstring[0] && !p->fprogram)
4179                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4180         CHECKCGERROR
4181
4182         // look up all the uniform variable names we care about, so we don't
4183         // have to look them up every time we set them
4184         if (p->vprogram)
4185         {
4186                 CHECKCGERROR
4187                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4188                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4189                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4190                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4191                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4192                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4193                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4194                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4195                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4196                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4197                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4198                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4199                 CHECKCGERROR
4200         }
4201         if (p->fprogram)
4202         {
4203                 CHECKCGERROR
4204                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4205                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4206                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4207                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4208                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4209                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4210                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4211                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4212                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4213                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4214                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4215                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4216                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4217                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4218                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4219                 p->fp_Texture_FogHeightTexture   = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4220                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4221                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4222                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4223                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4224                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4225                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4226                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4227                 p->fp_Texture_ShadowMapRect      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
4228                 p->fp_Texture_ShadowMapCube      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
4229                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4230                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4231                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4232                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4233                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4234                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4235                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4236                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4237                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4238                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4239                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4240                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4241                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4242                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4243                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4244                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4245                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4246                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4247                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4248                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4249                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4250                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4251                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4252                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4253                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4254                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4255                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4256                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4257                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4258                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4259                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4260                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4261                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4262                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4263                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4264                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4265                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4266                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4267                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4268                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4269                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4270                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4271                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4272                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4273                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4274                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4275                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4276                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4277                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4278                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4279                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4280                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4281                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4282                 CHECKCGERROR
4283         }
4284
4285         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4286                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4287         else
4288                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4289
4290         // free the strings
4291         if (vertstring)
4292                 Mem_Free(vertstring);
4293         if (geomstring)
4294                 Mem_Free(geomstring);
4295         if (fragstring)
4296                 Mem_Free(fragstring);
4297         if (vertexstring)
4298                 Mem_Free(vertexstring);
4299         if (geometrystring)
4300                 Mem_Free(geometrystring);
4301         if (fragmentstring)
4302                 Mem_Free(fragmentstring);
4303 }
4304
4305 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4306 {
4307         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4308         CHECKGLERROR
4309         CHECKCGERROR
4310         if (r_cg_permutation != perm)
4311         {
4312                 r_cg_permutation = perm;
4313                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4314                 {
4315                         if (!r_cg_permutation->compiled)
4316                                 R_CG_CompilePermutation(perm, mode, permutation);
4317                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4318                         {
4319                                 // remove features until we find a valid permutation
4320                                 int i;
4321                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4322                                 {
4323                                         // reduce i more quickly whenever it would not remove any bits
4324                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4325                                         if (!(permutation & j))
4326                                                 continue;
4327                                         permutation -= j;
4328                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4329                                         if (!r_cg_permutation->compiled)
4330                                                 R_CG_CompilePermutation(perm, mode, permutation);
4331                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4332                                                 break;
4333                                 }
4334                                 if (i >= SHADERPERMUTATION_COUNT)
4335                                 {
4336                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4337                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4338                                         return; // no bit left to clear, entire mode is broken
4339                                 }
4340                         }
4341                 }
4342                 CHECKGLERROR
4343                 CHECKCGERROR
4344                 if (r_cg_permutation->vprogram)
4345                 {
4346                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4347                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4348                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4349                 }
4350                 else
4351                 {
4352                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4353                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4354                 }
4355                 if (r_cg_permutation->fprogram)
4356                 {
4357                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4358                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4359                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4360                 }
4361                 else
4362                 {
4363                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4364                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4365                 }
4366         }
4367         CHECKCGERROR
4368         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4369         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4370         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4371 }
4372
4373 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4374 {
4375         cgGLSetTextureParameter(param, R_GetTexture(tex));
4376         cgGLEnableTextureParameter(param);
4377 }
4378 #endif
4379
4380 void R_GLSL_Restart_f(void)
4381 {
4382         unsigned int i, limit;
4383         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4384                 Mem_Free(glslshaderstring);
4385         glslshaderstring = NULL;
4386         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4387                 Mem_Free(cgshaderstring);
4388         cgshaderstring = NULL;
4389         switch(vid.renderpath)
4390         {
4391         case RENDERPATH_GL20:
4392                 {
4393                         r_glsl_permutation_t *p;
4394                         r_glsl_permutation = NULL;
4395                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4396                         for (i = 0;i < limit;i++)
4397                         {
4398                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4399                                 {
4400                                         GL_Backend_FreeProgram(p->program);
4401                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4402                                 }
4403                         }
4404                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4405                 }
4406                 break;
4407         case RENDERPATH_CGGL:
4408 #ifdef SUPPORTCG
4409                 {
4410                         r_cg_permutation_t *p;
4411                         r_cg_permutation = NULL;
4412                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4413                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4414                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4415                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4416                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4417                         for (i = 0;i < limit;i++)
4418                         {
4419                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4420                                 {
4421                                         if (p->vprogram)
4422                                                 cgDestroyProgram(p->vprogram);
4423                                         if (p->fprogram)
4424                                                 cgDestroyProgram(p->fprogram);
4425                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4426                                 }
4427                         }
4428                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4429                 }
4430                 break;
4431 #endif
4432         case RENDERPATH_GL13:
4433         case RENDERPATH_GL11:
4434                 break;
4435         }
4436 }
4437
4438 void R_GLSL_DumpShader_f(void)
4439 {
4440         int i;
4441         qfile_t *file;
4442
4443         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4444         if (file)
4445         {
4446                 FS_Print(file, "/* The engine may define the following macros:\n");
4447                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4448                 for (i = 0;i < SHADERMODE_COUNT;i++)
4449                         FS_Print(file, glslshadermodeinfo[i].pretext);
4450                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4451                         FS_Print(file, shaderpermutationinfo[i].pretext);
4452                 FS_Print(file, "*/\n");
4453                 FS_Print(file, builtinshaderstring);
4454                 FS_Close(file);
4455                 Con_Printf("glsl/default.glsl written\n");
4456         }
4457         else
4458                 Con_Printf("failed to write to glsl/default.glsl\n");
4459
4460 #ifdef SUPPORTCG
4461         file = FS_OpenRealFile("cg/default.cg", "w", false);
4462         if (file)
4463         {
4464                 FS_Print(file, "/* The engine may define the following macros:\n");
4465                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4466                 for (i = 0;i < SHADERMODE_COUNT;i++)
4467                         FS_Print(file, cgshadermodeinfo[i].pretext);
4468                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4469                         FS_Print(file, shaderpermutationinfo[i].pretext);
4470                 FS_Print(file, "*/\n");
4471                 FS_Print(file, builtincgshaderstring);
4472                 FS_Close(file);
4473                 Con_Printf("cg/default.cg written\n");
4474         }
4475         else
4476                 Con_Printf("failed to write to cg/default.cg\n");
4477 #endif
4478 }
4479
4480 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4481 {
4482         if (!second)
4483                 texturemode = GL_MODULATE;
4484         switch (vid.renderpath)
4485         {
4486         case RENDERPATH_GL20:
4487                 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))));
4488                 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
4489                 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, second);
4490                 break;
4491         case RENDERPATH_CGGL:
4492 #ifdef SUPPORTCG
4493                 CHECKCGERROR
4494                 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))));
4495                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4496                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4497 #endif
4498                 break;
4499         case RENDERPATH_GL13:
4500                 R_Mesh_TexBind(0, first );
4501                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4502                 R_Mesh_TexBind(1, second);
4503                 if (second)
4504                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4505                 break;
4506         case RENDERPATH_GL11:
4507                 R_Mesh_TexBind(0, first );
4508                 break;
4509         }
4510 }
4511
4512 void R_SetupShader_DepthOrShadow(void)
4513 {
4514         switch (vid.renderpath)
4515         {
4516         case RENDERPATH_GL20:
4517                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4518                 break;
4519         case RENDERPATH_CGGL:
4520 #ifdef SUPPORTCG
4521                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4522 #endif
4523                 break;
4524         case RENDERPATH_GL13:
4525                 R_Mesh_TexBind(0, 0);
4526                 R_Mesh_TexBind(1, 0);
4527                 break;
4528         case RENDERPATH_GL11:
4529                 R_Mesh_TexBind(0, 0);
4530                 break;
4531         }
4532 }
4533
4534 void R_SetupShader_ShowDepth(void)
4535 {
4536         switch (vid.renderpath)
4537         {
4538         case RENDERPATH_GL20:
4539                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4540                 break;
4541         case RENDERPATH_CGGL:
4542 #ifdef SUPPORTCG
4543                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4544 #endif
4545                 break;
4546         case RENDERPATH_GL13:
4547                 break;
4548         case RENDERPATH_GL11:
4549                 break;
4550         }
4551 }
4552
4553 extern qboolean r_shadow_usingdeferredprepass;
4554 extern cvar_t r_shadow_deferred_8bitrange;
4555 extern rtexture_t *r_shadow_attenuationgradienttexture;
4556 extern rtexture_t *r_shadow_attenuation2dtexture;
4557 extern rtexture_t *r_shadow_attenuation3dtexture;
4558 extern qboolean r_shadow_usingshadowmaprect;
4559 extern qboolean r_shadow_usingshadowmapcube;
4560 extern qboolean r_shadow_usingshadowmap2d;
4561 extern qboolean r_shadow_usingshadowmaportho;
4562 extern float r_shadow_shadowmap_texturescale[2];
4563 extern float r_shadow_shadowmap_parameters[4];
4564 extern qboolean r_shadow_shadowmapvsdct;
4565 extern qboolean r_shadow_shadowmapsampler;
4566 extern int r_shadow_shadowmappcf;
4567 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4568 extern rtexture_t *r_shadow_shadowmap2dtexture;
4569 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4570 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4571 extern matrix4x4_t r_shadow_shadowmapmatrix;
4572 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4573 extern int r_shadow_prepass_width;
4574 extern int r_shadow_prepass_height;
4575 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4576 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4577 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4578 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4579 extern cvar_t gl_mesh_separatearrays;
4580 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)
4581 {
4582         // select a permutation of the lighting shader appropriate to this
4583         // combination of texture, entity, light source, and fogging, only use the
4584         // minimum features necessary to avoid wasting rendering time in the
4585         // fragment shader on features that are not being used
4586         unsigned int permutation = 0;
4587         unsigned int mode = 0;
4588         float m16f[16];
4589         if (rsurfacepass == RSURFPASS_BACKGROUND)
4590         {
4591                 // distorted background
4592                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4593                         mode = SHADERMODE_WATER;
4594                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
4595                         mode = SHADERMODE_REFRACTION;
4596                 else
4597                 {
4598                         mode = SHADERMODE_GENERIC;
4599                         permutation |= SHADERPERMUTATION_DIFFUSE;
4600                 }
4601                 GL_AlphaTest(false);
4602                 GL_BlendFunc(GL_ONE, GL_ZERO);
4603         }
4604         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4605         {
4606                 if (r_glsl_offsetmapping.integer)
4607                 {
4608                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4609                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4610                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4611                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4612                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4613                         {
4614                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4615                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4616                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4617                         }
4618                 }
4619                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4620                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4621                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4622                         permutation |= SHADERPERMUTATION_ALPHAKILL;
4623                 // normalmap (deferred prepass), may use alpha test on diffuse
4624                 mode = SHADERMODE_DEFERREDGEOMETRY;
4625                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4626                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4627                 GL_AlphaTest(false);
4628                 GL_BlendFunc(GL_ONE, GL_ZERO);
4629         }
4630         else if (rsurfacepass == RSURFPASS_RTLIGHT)
4631         {
4632                 if (r_glsl_offsetmapping.integer)
4633                 {
4634                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4635                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4636                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4637                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4638                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4639                         {
4640                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4641                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4642                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4643                         }
4644                 }
4645                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4646                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4647                 // light source
4648                 mode = SHADERMODE_LIGHTSOURCE;
4649                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4650                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4651                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4652                         permutation |= SHADERPERMUTATION_CUBEFILTER;
4653                 if (diffusescale > 0)
4654                         permutation |= SHADERPERMUTATION_DIFFUSE;
4655                 if (specularscale > 0)
4656                 {
4657                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4658                         if (r_shadow_glossexact.integer)
4659                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4660                 }
4661                 if (r_refdef.fogenabled)
4662                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4663                 if (rsurface.texture->colormapping)
4664                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4665                 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4666                 {
4667                         if (r_shadow_usingshadowmaprect)
4668                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4669                         if (r_shadow_usingshadowmap2d)
4670                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4671                         if (r_shadow_usingshadowmapcube)
4672                                 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4673                         else if(r_shadow_shadowmapvsdct)
4674                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4675
4676                         if (r_shadow_shadowmapsampler)
4677                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4678                         if (r_shadow_shadowmappcf > 1)
4679                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4680                         else if (r_shadow_shadowmappcf)
4681                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4682                 }
4683                 if (rsurface.texture->reflectmasktexture)
4684                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4685                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4686                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4687         }
4688         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4689         {
4690                 if (r_glsl_offsetmapping.integer)
4691                 {
4692                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4693                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4694                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4695                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4696                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4697                         {
4698                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4699                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4700                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4701                         }
4702                 }
4703                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4704                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4705                 // unshaded geometry (fullbright or ambient model lighting)
4706                 mode = SHADERMODE_FLATCOLOR;
4707                 ambientscale = diffusescale = specularscale = 0;
4708                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4709                         permutation |= SHADERPERMUTATION_GLOW;
4710                 if (r_refdef.fogenabled)
4711                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4712                 if (rsurface.texture->colormapping)
4713                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4714                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4715                 {
4716                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4717                         if (r_shadow_usingshadowmaprect)
4718                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4719                         if (r_shadow_usingshadowmap2d)
4720                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4721
4722                         if (r_shadow_shadowmapsampler)
4723                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4724                         if (r_shadow_shadowmappcf > 1)
4725                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4726                         else if (r_shadow_shadowmappcf)
4727                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4728                 }
4729                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4730                         permutation |= SHADERPERMUTATION_REFLECTION;
4731                 if (rsurface.texture->reflectmasktexture)
4732                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4733                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4734                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4735         }
4736         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4737         {
4738                 if (r_glsl_offsetmapping.integer)
4739                 {
4740                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4741                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4742                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4743                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4744                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4745                         {
4746                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4747                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4748                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4749                         }
4750                 }
4751                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4752                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4753                 // directional model lighting
4754                 mode = SHADERMODE_LIGHTDIRECTION;
4755                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4756                         permutation |= SHADERPERMUTATION_GLOW;
4757                 permutation |= SHADERPERMUTATION_DIFFUSE;
4758                 if (specularscale > 0)
4759                 {
4760                         permutation |= SHADERPERMUTATION_SPECULAR;
4761                         if (r_shadow_glossexact.integer)
4762                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4763                 }
4764                 if (r_refdef.fogenabled)
4765                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4766                 if (rsurface.texture->colormapping)
4767                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4768                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4769                 {
4770                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4771                         if (r_shadow_usingshadowmaprect)
4772                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4773                         if (r_shadow_usingshadowmap2d)
4774                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4775
4776                         if (r_shadow_shadowmapsampler)
4777                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4778                         if (r_shadow_shadowmappcf > 1)
4779                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4780                         else if (r_shadow_shadowmappcf)
4781                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4782                 }
4783                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4784                         permutation |= SHADERPERMUTATION_REFLECTION;
4785                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4786                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4787                 if (rsurface.texture->reflectmasktexture)
4788                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4789                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4790                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4791         }
4792         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
4793         {
4794                 if (r_glsl_offsetmapping.integer)
4795                 {
4796                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4797                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4798                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4799                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4800                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4801                         {
4802                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4803                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4804                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4805                         }
4806                 }
4807                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4808                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4809                 // ambient model lighting
4810                 mode = SHADERMODE_LIGHTDIRECTION;
4811                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4812                         permutation |= SHADERPERMUTATION_GLOW;
4813                 if (r_refdef.fogenabled)
4814                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4815                 if (rsurface.texture->colormapping)
4816                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4817                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4818                 {
4819                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4820                         if (r_shadow_usingshadowmaprect)
4821                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4822                         if (r_shadow_usingshadowmap2d)
4823                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4824
4825                         if (r_shadow_shadowmapsampler)
4826                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4827                         if (r_shadow_shadowmappcf > 1)
4828                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4829                         else if (r_shadow_shadowmappcf)
4830                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4831                 }
4832                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4833                         permutation |= SHADERPERMUTATION_REFLECTION;
4834                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4835                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4836                 if (rsurface.texture->reflectmasktexture)
4837                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4838                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4839                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4840         }
4841         else
4842         {
4843                 if (r_glsl_offsetmapping.integer)
4844                 {
4845                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4846                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4847                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4848                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4849                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4850                         {
4851                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4852                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4853                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4854                         }
4855                 }
4856                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4857                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4858                 // lightmapped wall
4859                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4860                         permutation |= SHADERPERMUTATION_GLOW;
4861                 if (r_refdef.fogenabled)
4862                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4863                 if (rsurface.texture->colormapping)
4864                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4865                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4866                 {
4867                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4868                         if (r_shadow_usingshadowmaprect)
4869                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4870                         if (r_shadow_usingshadowmap2d)
4871                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4872
4873                         if (r_shadow_shadowmapsampler)
4874                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4875                         if (r_shadow_shadowmappcf > 1)
4876                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4877                         else if (r_shadow_shadowmappcf)
4878                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4879                 }
4880                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4881                         permutation |= SHADERPERMUTATION_REFLECTION;
4882                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4883                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4884                 if (rsurface.texture->reflectmasktexture)
4885                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4886                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
4887                 {
4888                         // deluxemapping (light direction texture)
4889                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
4890                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
4891                         else
4892                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4893                         permutation |= SHADERPERMUTATION_DIFFUSE;
4894                         if (specularscale > 0)
4895                         {
4896                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4897                                 if (r_shadow_glossexact.integer)
4898                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4899                         }
4900                 }
4901                 else if (r_glsl_deluxemapping.integer >= 2)
4902                 {
4903                         // fake deluxemapping (uniform light direction in tangentspace)
4904                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4905                         permutation |= SHADERPERMUTATION_DIFFUSE;
4906                         if (specularscale > 0)
4907                         {
4908                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4909                                 if (r_shadow_glossexact.integer)
4910                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4911                         }
4912                 }
4913                 else if (rsurface.uselightmaptexture)
4914                 {
4915                         // ordinary lightmapping (q1bsp, q3bsp)
4916                         mode = SHADERMODE_LIGHTMAP;
4917                 }
4918                 else
4919                 {
4920                         // ordinary vertex coloring (q3bsp)
4921                         mode = SHADERMODE_VERTEXCOLOR;
4922                 }
4923                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4924                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4925         }
4926         switch(vid.renderpath)
4927         {
4928         case RENDERPATH_GL20:
4929                 if (gl_mesh_separatearrays.integer)
4930                 {
4931                         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);
4932                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
4933                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
4934                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
4935                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
4936                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
4937                         R_Mesh_TexCoordPointer(3, 4, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
4938                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
4939                 }
4940                 else
4941                 {
4942                         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);
4943                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
4944                 }
4945                 R_SetupShader_SetPermutationGLSL(mode, permutation);
4946                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
4947                 if (mode == SHADERMODE_LIGHTSOURCE)
4948                 {
4949                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
4950                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
4951                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
4952                         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);
4953                         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);
4954                         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);
4955         
4956                         // additive passes are only darkened by fog, not tinted
4957                         if (r_glsl_permutation->loc_FogColor >= 0)
4958                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4959                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4960                 }
4961                 else
4962                 {
4963                         if (mode == SHADERMODE_FLATCOLOR)
4964                         {
4965                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
4966                         }
4967                         else if (mode == SHADERMODE_LIGHTDIRECTION)
4968                         {
4969                                 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]);
4970                                 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]);
4971                                 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);
4972                                 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);
4973                                 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);
4974                                 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]);
4975                                 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]);
4976                         }
4977                         else
4978                         {
4979                                 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]);
4980                                 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]);
4981                                 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);
4982                                 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);
4983                                 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);
4984                         }
4985                         // additive passes are only darkened by fog, not tinted
4986                         if (r_glsl_permutation->loc_FogColor >= 0)
4987                         {
4988                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4989                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4990                                 else
4991                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4992                         }
4993                         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);
4994                         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]);
4995                         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]);
4996                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
4997                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
4998                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
4999                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5000                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5001                 }
5002                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5003                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5004                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5005                 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]);
5006                 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]);
5007
5008                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5009                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
5010                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5011                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5012                 {
5013                         if (rsurface.texture->pantstexture)
5014                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5015                         else
5016                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5017                 }
5018                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5019                 {
5020                         if (rsurface.texture->shirttexture)
5021                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5022                         else
5023                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5024                 }
5025                 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]);
5026                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5027                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5028                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5029                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5030                 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]);
5031                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5032
5033         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
5034         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
5035         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
5036                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5037                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5038                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5039                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5040                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5041                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5042                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5043                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5044                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5045                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5046                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5047                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5048                 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5049                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5050                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_white                                     );
5051                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_blanknormalmap                            );
5052                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5053                 if (r_glsl_permutation->loc_Texture_Refraction      >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , r_texture_white                                     );
5054                 if (r_glsl_permutation->loc_Texture_Reflection      >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , r_texture_white                                     );
5055                 if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5056                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5057                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5058                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5059                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5060                 {
5061                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
5062                         if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT, r_shadow_shadowmaprectangletexture                  );
5063                         if (rsurface.rtlight)
5064                         {
5065                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5066                                 if (r_shadow_usingshadowmapcube)
5067                                         if (r_glsl_permutation->loc_Texture_ShadowMapCube   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE     , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5068                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5069                         }
5070                 }
5071                 CHECKGLERROR
5072                 break;
5073         case RENDERPATH_CGGL:
5074 #ifdef SUPPORTCG
5075                 if (gl_mesh_separatearrays.integer)
5076                 {
5077                         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);
5078                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5079                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5080                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5081                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5082                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5083                         R_Mesh_TexCoordPointer(3, 4, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5084                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5085                 }
5086                 else
5087                 {
5088                         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);
5089                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5090                 }
5091                 R_SetupShader_SetPermutationCG(mode, permutation);
5092                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
5093                 if (mode == SHADERMODE_LIGHTSOURCE)
5094                 {
5095                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
5096                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5097                 }
5098                 else
5099                 {
5100                         if (mode == SHADERMODE_LIGHTDIRECTION)
5101                         {
5102                                 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
5103                         }
5104                 }
5105                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
5106                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
5107                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
5108                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5109                 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
5110                 CHECKGLERROR
5111
5112                 if (mode == SHADERMODE_LIGHTSOURCE)
5113                 {
5114                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5115                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
5116                         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
5117                         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
5118                         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
5119
5120                         // additive passes are only darkened by fog, not tinted
5121                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
5122                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5123                 }
5124                 else
5125                 {
5126                         if (mode == SHADERMODE_FLATCOLOR)
5127                         {
5128                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);CHECKCGERROR
5129                         }
5130                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5131                         {
5132                                 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
5133                                 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
5134                                 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
5135                                 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
5136                                 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
5137                                 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
5138                                 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
5139                         }
5140                         else
5141                         {
5142                                 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
5143                                 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
5144                                 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
5145                                 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
5146                                 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
5147                         }
5148                         // additive passes are only darkened by fog, not tinted
5149                         if (r_cg_permutation->fp_FogColor)
5150                         {
5151                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5152                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
5153                                 else
5154                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5155                                 CHECKCGERROR
5156                         }
5157                         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
5158                         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
5159                         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
5160                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
5161                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
5162                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
5163                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
5164                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5165                 }
5166                 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
5167                 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
5168                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
5169                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
5170                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5171                 if (r_cg_permutation->fp_Color_Pants)
5172                 {
5173                         if (rsurface.texture->pantstexture)
5174                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5175                         else
5176                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
5177                         CHECKCGERROR
5178                 }
5179                 if (r_cg_permutation->fp_Color_Shirt)
5180                 {
5181                         if (rsurface.texture->shirttexture)
5182                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5183                         else
5184                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
5185                         CHECKCGERROR
5186                 }
5187                 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
5188                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
5189                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
5190                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
5191                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
5192                 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
5193                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5194
5195         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
5196         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
5197         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
5198                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
5199                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
5200                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
5201                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
5202                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
5203                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
5204                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
5205                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
5206                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
5207                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
5208                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
5209                 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
5210                 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
5211                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
5212                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , r_texture_white                                     );CHECKCGERROR
5213                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , r_texture_blanknormalmap                            );CHECKCGERROR
5214                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
5215                 if (r_cg_permutation->fp_Texture_Refraction     ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction     , r_texture_white                                     );CHECKCGERROR
5216                 if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , r_texture_white                                     );CHECKCGERROR
5217                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
5218                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
5219                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
5220                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
5221                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5222                 {
5223                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5224                         if (r_cg_permutation->fp_Texture_ShadowMapRect  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
5225                         if (rsurface.rtlight)
5226                         {
5227                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
5228                                 if (r_shadow_usingshadowmapcube)
5229                                         if (r_cg_permutation->fp_Texture_ShadowMapCube  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5230                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
5231                         }
5232                 }
5233
5234                 CHECKGLERROR
5235 #endif
5236                 break;
5237         case RENDERPATH_GL13:
5238         case RENDERPATH_GL11:
5239                 break;
5240         }
5241 }
5242
5243 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
5244 {
5245         // select a permutation of the lighting shader appropriate to this
5246         // combination of texture, entity, light source, and fogging, only use the
5247         // minimum features necessary to avoid wasting rendering time in the
5248         // fragment shader on features that are not being used
5249         unsigned int permutation = 0;
5250         unsigned int mode = 0;
5251         const float *lightcolorbase = rtlight->currentcolor;
5252         float ambientscale = rtlight->ambientscale;
5253         float diffusescale = rtlight->diffusescale;
5254         float specularscale = rtlight->specularscale;
5255         // this is the location of the light in view space
5256         vec3_t viewlightorigin;
5257         // this transforms from view space (camera) to light space (cubemap)
5258         matrix4x4_t viewtolight;
5259         matrix4x4_t lighttoview;
5260         float viewtolight16f[16];
5261         float range = 1.0f / r_shadow_deferred_8bitrange.value;
5262         // light source
5263         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
5264         if (rtlight->currentcubemap != r_texture_whitecube)
5265                 permutation |= SHADERPERMUTATION_CUBEFILTER;
5266         if (diffusescale > 0)
5267                 permutation |= SHADERPERMUTATION_DIFFUSE;
5268         if (specularscale > 0)
5269         {
5270                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5271                 if (r_shadow_glossexact.integer)
5272                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5273         }
5274         if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
5275         {
5276                 if (r_shadow_usingshadowmaprect)
5277                         permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5278                 if (r_shadow_usingshadowmap2d)
5279                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5280                 if (r_shadow_usingshadowmapcube)
5281                         permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
5282                 else if(r_shadow_shadowmapvsdct)
5283                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5284
5285                 if (r_shadow_shadowmapsampler)
5286                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5287                 if (r_shadow_shadowmappcf > 1)
5288                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5289                 else if (r_shadow_shadowmappcf)
5290                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5291         }
5292         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
5293         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
5294         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
5295         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
5296         switch(vid.renderpath)
5297         {
5298         case RENDERPATH_GL20:
5299                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5300                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5301                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
5302                 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);
5303                 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);
5304                 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);
5305                 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]);
5306                 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]);
5307                 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));
5308                 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]);
5309                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5310
5311                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
5312                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
5313                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
5314                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
5315                 if (r_glsl_permutation->loc_Texture_ShadowMapRect     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT      , r_shadow_shadowmaprectangletexture                  );
5316                 if (r_shadow_usingshadowmapcube)
5317                         if (r_glsl_permutation->loc_Texture_ShadowMapCube     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE      , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5318                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
5319                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
5320                 break;
5321         case RENDERPATH_CGGL:
5322 #ifdef SUPPORTCG
5323                 R_SetupShader_SetPermutationCG(mode, permutation);
5324                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
5325                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
5326                 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
5327                 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
5328                 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
5329                 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
5330                 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
5331                 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
5332                 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
5333                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5334
5335                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
5336                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
5337                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
5338                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
5339                 if (r_cg_permutation->fp_Texture_ShadowMapRect    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
5340                 if (r_shadow_usingshadowmapcube)
5341                         if (r_cg_permutation->fp_Texture_ShadowMapCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5342                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5343                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
5344 #endif
5345                 break;
5346         case RENDERPATH_GL13:
5347         case RENDERPATH_GL11:
5348                 break;
5349         }
5350 }
5351
5352 #define SKINFRAME_HASH 1024
5353
5354 typedef struct
5355 {
5356         int loadsequence; // incremented each level change
5357         memexpandablearray_t array;
5358         skinframe_t *hash[SKINFRAME_HASH];
5359 }
5360 r_skinframe_t;
5361 r_skinframe_t r_skinframe;
5362
5363 void R_SkinFrame_PrepareForPurge(void)
5364 {
5365         r_skinframe.loadsequence++;
5366         // wrap it without hitting zero
5367         if (r_skinframe.loadsequence >= 200)
5368                 r_skinframe.loadsequence = 1;
5369 }
5370
5371 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5372 {
5373         if (!skinframe)
5374                 return;
5375         // mark the skinframe as used for the purging code
5376         skinframe->loadsequence = r_skinframe.loadsequence;
5377 }
5378
5379 void R_SkinFrame_Purge(void)
5380 {
5381         int i;
5382         skinframe_t *s;
5383         for (i = 0;i < SKINFRAME_HASH;i++)
5384         {
5385                 for (s = r_skinframe.hash[i];s;s = s->next)
5386                 {
5387                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5388                         {
5389                                 if (s->merged == s->base)
5390                                         s->merged = NULL;
5391                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5392                                 R_PurgeTexture(s->stain );s->stain  = NULL;
5393                                 R_PurgeTexture(s->merged);s->merged = NULL;
5394                                 R_PurgeTexture(s->base  );s->base   = NULL;
5395                                 R_PurgeTexture(s->pants );s->pants  = NULL;
5396                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
5397                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
5398                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
5399                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
5400                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
5401                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
5402                                 s->loadsequence = 0;
5403                         }
5404                 }
5405         }
5406 }
5407
5408 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5409         skinframe_t *item;
5410         char basename[MAX_QPATH];
5411
5412         Image_StripImageExtension(name, basename, sizeof(basename));
5413
5414         if( last == NULL ) {
5415                 int hashindex;
5416                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5417                 item = r_skinframe.hash[hashindex];
5418         } else {
5419                 item = last->next;
5420         }
5421
5422         // linearly search through the hash bucket
5423         for( ; item ; item = item->next ) {
5424                 if( !strcmp( item->basename, basename ) ) {
5425                         return item;
5426                 }
5427         }
5428         return NULL;
5429 }
5430
5431 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5432 {
5433         skinframe_t *item;
5434         int hashindex;
5435         char basename[MAX_QPATH];
5436
5437         Image_StripImageExtension(name, basename, sizeof(basename));
5438
5439         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5440         for (item = r_skinframe.hash[hashindex];item;item = item->next)
5441                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5442                         break;
5443
5444         if (!item) {
5445                 rtexture_t *dyntexture;
5446                 // check whether its a dynamic texture
5447                 dyntexture = CL_GetDynTexture( basename );
5448                 if (!add && !dyntexture)
5449                         return NULL;
5450                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5451                 memset(item, 0, sizeof(*item));
5452                 strlcpy(item->basename, basename, sizeof(item->basename));
5453                 item->base = dyntexture; // either NULL or dyntexture handle
5454                 item->textureflags = textureflags;
5455                 item->comparewidth = comparewidth;
5456                 item->compareheight = compareheight;
5457                 item->comparecrc = comparecrc;
5458                 item->next = r_skinframe.hash[hashindex];
5459                 r_skinframe.hash[hashindex] = item;
5460         }
5461         else if( item->base == NULL )
5462         {
5463                 rtexture_t *dyntexture;
5464                 // check whether its a dynamic texture
5465                 // 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]
5466                 dyntexture = CL_GetDynTexture( basename );
5467                 item->base = dyntexture; // either NULL or dyntexture handle
5468         }
5469
5470         R_SkinFrame_MarkUsed(item);
5471         return item;
5472 }
5473
5474 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5475         { \
5476                 unsigned long long avgcolor[5], wsum; \
5477                 int pix, comp, w; \
5478                 avgcolor[0] = 0; \
5479                 avgcolor[1] = 0; \
5480                 avgcolor[2] = 0; \
5481                 avgcolor[3] = 0; \
5482                 avgcolor[4] = 0; \
5483                 wsum = 0; \
5484                 for(pix = 0; pix < cnt; ++pix) \
5485                 { \
5486                         w = 0; \
5487                         for(comp = 0; comp < 3; ++comp) \
5488                                 w += getpixel; \
5489                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5490                         { \
5491                                 ++wsum; \
5492                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5493                                 w = getpixel; \
5494                                 for(comp = 0; comp < 3; ++comp) \
5495                                         avgcolor[comp] += getpixel * w; \
5496                                 avgcolor[3] += w; \
5497                         } \
5498                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5499                         avgcolor[4] += getpixel; \
5500                 } \
5501                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5502                         avgcolor[3] = 1; \
5503                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5504                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5505                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5506                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5507         }
5508
5509 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5510 {
5511         int j;
5512         unsigned char *pixels;
5513         unsigned char *bumppixels;
5514         unsigned char *basepixels = NULL;
5515         int basepixels_width = 0;
5516         int basepixels_height = 0;
5517         skinframe_t *skinframe;
5518         rtexture_t *ddsbase = NULL;
5519         qboolean ddshasalpha = false;
5520         float ddsavgcolor[4];
5521         char basename[MAX_QPATH];
5522
5523         if (cls.state == ca_dedicated)
5524                 return NULL;
5525
5526         // return an existing skinframe if already loaded
5527         // if loading of the first image fails, don't make a new skinframe as it
5528         // would cause all future lookups of this to be missing
5529         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5530         if (skinframe && skinframe->base)
5531                 return skinframe;
5532
5533         Image_StripImageExtension(name, basename, sizeof(basename));
5534
5535         // check for DDS texture file first
5536         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor)))
5537         {
5538                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer);
5539                 if (basepixels == NULL)
5540                         return NULL;
5541         }
5542
5543         if (developer_loading.integer)
5544                 Con_Printf("loading skin \"%s\"\n", name);
5545
5546         // we've got some pixels to store, so really allocate this new texture now
5547         if (!skinframe)
5548                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5549         skinframe->stain = NULL;
5550         skinframe->merged = NULL;
5551         skinframe->base = NULL;
5552         skinframe->pants = NULL;
5553         skinframe->shirt = NULL;
5554         skinframe->nmap = NULL;
5555         skinframe->gloss = NULL;
5556         skinframe->glow = NULL;
5557         skinframe->fog = NULL;
5558         skinframe->reflect = NULL;
5559         skinframe->hasalpha = false;
5560
5561         if (ddsbase)
5562         {
5563                 skinframe->base = ddsbase;
5564                 skinframe->hasalpha = ddshasalpha;
5565                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5566                 if (r_loadfog && skinframe->hasalpha)
5567                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5568                 //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]);
5569         }
5570         else
5571         {
5572                 basepixels_width = image_width;
5573                 basepixels_height = image_height;
5574                 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);
5575                 if (textureflags & TEXF_ALPHA)
5576                 {
5577                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5578                         {
5579                                 if (basepixels[j] < 255)
5580                                 {
5581                                         skinframe->hasalpha = true;
5582                                         break;
5583                                 }
5584                         }
5585                         if (r_loadfog && skinframe->hasalpha)
5586                         {
5587                                 // has transparent pixels
5588                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5589                                 for (j = 0;j < image_width * image_height * 4;j += 4)
5590                                 {
5591                                         pixels[j+0] = 255;
5592                                         pixels[j+1] = 255;
5593                                         pixels[j+2] = 255;
5594                                         pixels[j+3] = basepixels[j+3];
5595                                 }
5596                                 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);
5597                                 Mem_Free(pixels);
5598                         }
5599                 }
5600                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5601                 //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]);
5602                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5603                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true);
5604                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
5605                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true);
5606         }
5607
5608         if (r_loaddds)
5609         {
5610                 if (r_loadnormalmap)
5611                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5612                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL);
5613                 if (r_loadgloss)
5614                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL);
5615                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL);
5616                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL);
5617                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL);
5618         }
5619
5620         // _norm is the name used by tenebrae and has been adopted as standard
5621         if (r_loadnormalmap && skinframe->nmap == NULL)
5622         {
5623                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false)) != NULL)
5624                 {
5625                         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);
5626                         Mem_Free(pixels);
5627                         pixels = NULL;
5628                 }
5629                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false)) != NULL)
5630                 {
5631                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5632                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5633                         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);
5634                         Mem_Free(pixels);
5635                         Mem_Free(bumppixels);
5636                 }
5637                 else if (r_shadow_bumpscale_basetexture.value > 0)
5638                 {
5639                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5640                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5641                         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);
5642                         Mem_Free(pixels);
5643                 }
5644                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
5645                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true);
5646         }
5647
5648         // _luma is supported only for tenebrae compatibility
5649         // _glow is the preferred name
5650         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))))
5651         {
5652                 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);
5653                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
5654                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true);
5655                 Mem_Free(pixels);pixels = NULL;
5656         }
5657
5658         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5659         {
5660                 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);
5661                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
5662                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true);
5663                 Mem_Free(pixels);
5664                 pixels = NULL;
5665         }
5666
5667         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5668         {
5669                 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);
5670                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
5671                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true);
5672                 Mem_Free(pixels);
5673                 pixels = NULL;
5674         }
5675
5676         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5677         {
5678                 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);
5679                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
5680                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true);
5681                 Mem_Free(pixels);
5682                 pixels = NULL;
5683         }
5684
5685         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5686         {
5687                 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);
5688                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
5689                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true);
5690                 Mem_Free(pixels);
5691                 pixels = NULL;
5692         }
5693
5694         if (basepixels)
5695                 Mem_Free(basepixels);
5696
5697         return skinframe;
5698 }
5699
5700 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
5701 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
5702 {
5703         int i;
5704         unsigned char *temp1, *temp2;
5705         skinframe_t *skinframe;
5706
5707         if (cls.state == ca_dedicated)
5708                 return NULL;
5709
5710         // if already loaded just return it, otherwise make a new skinframe
5711         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
5712         if (skinframe && skinframe->base)
5713                 return skinframe;
5714
5715         skinframe->stain = NULL;
5716         skinframe->merged = NULL;
5717         skinframe->base = NULL;
5718         skinframe->pants = NULL;
5719         skinframe->shirt = NULL;
5720         skinframe->nmap = NULL;
5721         skinframe->gloss = NULL;
5722         skinframe->glow = NULL;
5723         skinframe->fog = NULL;
5724         skinframe->reflect = NULL;
5725         skinframe->hasalpha = false;
5726
5727         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5728         if (!skindata)
5729                 return NULL;
5730
5731         if (developer_loading.integer)
5732                 Con_Printf("loading 32bit skin \"%s\"\n", name);
5733
5734         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
5735         {
5736                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5737                 temp2 = temp1 + width * height * 4;
5738                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5739                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5740                 Mem_Free(temp1);
5741         }
5742         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5743         if (textureflags & TEXF_ALPHA)
5744         {
5745                 for (i = 3;i < width * height * 4;i += 4)
5746                 {
5747                         if (skindata[i] < 255)
5748                         {
5749                                 skinframe->hasalpha = true;
5750                                 break;
5751                         }
5752                 }
5753                 if (r_loadfog && skinframe->hasalpha)
5754                 {
5755                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
5756                         memcpy(fogpixels, skindata, width * height * 4);
5757                         for (i = 0;i < width * height * 4;i += 4)
5758                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
5759                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5760                         Mem_Free(fogpixels);
5761                 }
5762         }
5763
5764         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
5765         //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]);
5766
5767         return skinframe;
5768 }
5769
5770 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
5771 {
5772         int i;
5773         int featuresmask;
5774         skinframe_t *skinframe;
5775
5776         if (cls.state == ca_dedicated)
5777                 return NULL;
5778
5779         // if already loaded just return it, otherwise make a new skinframe
5780         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5781         if (skinframe && skinframe->base)
5782                 return skinframe;
5783
5784         skinframe->stain = NULL;
5785         skinframe->merged = NULL;
5786         skinframe->base = NULL;
5787         skinframe->pants = NULL;
5788         skinframe->shirt = NULL;
5789         skinframe->nmap = NULL;
5790         skinframe->gloss = NULL;
5791         skinframe->glow = NULL;
5792         skinframe->fog = NULL;
5793         skinframe->reflect = NULL;
5794         skinframe->hasalpha = false;
5795
5796         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5797         if (!skindata)
5798                 return NULL;
5799
5800         if (developer_loading.integer)
5801                 Con_Printf("loading quake skin \"%s\"\n", name);
5802
5803         // 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)
5804         skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
5805         memcpy(skinframe->qpixels, skindata, width*height);
5806         skinframe->qwidth = width;
5807         skinframe->qheight = height;
5808
5809         featuresmask = 0;
5810         for (i = 0;i < width * height;i++)
5811                 featuresmask |= palette_featureflags[skindata[i]];
5812
5813         skinframe->hasalpha = false;
5814         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
5815         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
5816         skinframe->qgeneratemerged = true;
5817         skinframe->qgeneratebase = skinframe->qhascolormapping;
5818         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
5819
5820         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
5821         //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]);
5822
5823         return skinframe;
5824 }
5825
5826 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
5827 {
5828         int width;
5829         int height;
5830         unsigned char *skindata;
5831
5832         if (!skinframe->qpixels)
5833                 return;
5834
5835         if (!skinframe->qhascolormapping)
5836                 colormapped = false;
5837
5838         if (colormapped)
5839         {
5840                 if (!skinframe->qgeneratebase)
5841                         return;
5842         }
5843         else
5844         {
5845                 if (!skinframe->qgeneratemerged)
5846                         return;
5847         }
5848
5849         width = skinframe->qwidth;
5850         height = skinframe->qheight;
5851         skindata = skinframe->qpixels;
5852
5853         if (skinframe->qgeneratenmap)
5854         {
5855                 unsigned char *temp1, *temp2;
5856                 skinframe->qgeneratenmap = false;
5857                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5858                 temp2 = temp1 + width * height * 4;
5859                 // use either a custom palette or the quake palette
5860                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
5861                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5862                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5863                 Mem_Free(temp1);
5864         }
5865
5866         if (skinframe->qgenerateglow)
5867         {
5868                 skinframe->qgenerateglow = false;
5869                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
5870         }
5871
5872         if (colormapped)
5873         {
5874                 skinframe->qgeneratebase = false;
5875                 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);
5876                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
5877                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
5878         }
5879         else
5880         {
5881                 skinframe->qgeneratemerged = false;
5882                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
5883         }
5884
5885         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
5886         {
5887                 Mem_Free(skinframe->qpixels);
5888                 skinframe->qpixels = NULL;
5889         }
5890 }
5891
5892 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)
5893 {
5894         int i;
5895         skinframe_t *skinframe;
5896
5897         if (cls.state == ca_dedicated)
5898                 return NULL;
5899
5900         // if already loaded just return it, otherwise make a new skinframe
5901         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5902         if (skinframe && skinframe->base)
5903                 return skinframe;
5904
5905         skinframe->stain = NULL;
5906         skinframe->merged = NULL;
5907         skinframe->base = NULL;
5908         skinframe->pants = NULL;
5909         skinframe->shirt = NULL;
5910         skinframe->nmap = NULL;
5911         skinframe->gloss = NULL;
5912         skinframe->glow = NULL;
5913         skinframe->fog = NULL;
5914         skinframe->reflect = NULL;
5915         skinframe->hasalpha = false;
5916
5917         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5918         if (!skindata)
5919                 return NULL;
5920
5921         if (developer_loading.integer)
5922                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
5923
5924         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
5925         if (textureflags & TEXF_ALPHA)
5926         {
5927                 for (i = 0;i < width * height;i++)
5928                 {
5929                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
5930                         {
5931                                 skinframe->hasalpha = true;
5932                                 break;
5933                         }
5934                 }
5935                 if (r_loadfog && skinframe->hasalpha)
5936                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
5937         }
5938
5939         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
5940         //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]);
5941
5942         return skinframe;
5943 }
5944
5945 skinframe_t *R_SkinFrame_LoadMissing(void)
5946 {
5947         skinframe_t *skinframe;
5948
5949         if (cls.state == ca_dedicated)
5950                 return NULL;
5951
5952         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
5953         skinframe->stain = NULL;
5954         skinframe->merged = NULL;
5955         skinframe->base = NULL;
5956         skinframe->pants = NULL;
5957         skinframe->shirt = NULL;
5958         skinframe->nmap = NULL;
5959         skinframe->gloss = NULL;
5960         skinframe->glow = NULL;
5961         skinframe->fog = NULL;
5962         skinframe->reflect = NULL;
5963         skinframe->hasalpha = false;
5964
5965         skinframe->avgcolor[0] = rand() / RAND_MAX;
5966         skinframe->avgcolor[1] = rand() / RAND_MAX;
5967         skinframe->avgcolor[2] = rand() / RAND_MAX;
5968         skinframe->avgcolor[3] = 1;
5969
5970         return skinframe;
5971 }
5972
5973 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
5974 typedef struct suffixinfo_s
5975 {
5976         char *suffix;
5977         qboolean flipx, flipy, flipdiagonal;
5978 }
5979 suffixinfo_t;
5980 static suffixinfo_t suffix[3][6] =
5981 {
5982         {
5983                 {"px",   false, false, false},
5984                 {"nx",   false, false, false},
5985                 {"py",   false, false, false},
5986                 {"ny",   false, false, false},
5987                 {"pz",   false, false, false},
5988                 {"nz",   false, false, false}
5989         },
5990         {
5991                 {"posx", false, false, false},
5992                 {"negx", false, false, false},
5993                 {"posy", false, false, false},
5994                 {"negy", false, false, false},
5995                 {"posz", false, false, false},
5996                 {"negz", false, false, false}
5997         },
5998         {
5999                 {"rt",    true, false,  true},
6000                 {"lf",   false,  true,  true},
6001                 {"ft",    true,  true, false},
6002                 {"bk",   false, false, false},
6003                 {"up",    true, false,  true},
6004                 {"dn",    true, false,  true}
6005         }
6006 };
6007
6008 static int componentorder[4] = {0, 1, 2, 3};
6009
6010 rtexture_t *R_LoadCubemap(const char *basename)
6011 {
6012         int i, j, cubemapsize;
6013         unsigned char *cubemappixels, *image_buffer;
6014         rtexture_t *cubemaptexture;
6015         char name[256];
6016         // must start 0 so the first loadimagepixels has no requested width/height
6017         cubemapsize = 0;
6018         cubemappixels = NULL;
6019         cubemaptexture = NULL;
6020         // keep trying different suffix groups (posx, px, rt) until one loads
6021         for (j = 0;j < 3 && !cubemappixels;j++)
6022         {
6023                 // load the 6 images in the suffix group
6024                 for (i = 0;i < 6;i++)
6025                 {
6026                         // generate an image name based on the base and and suffix
6027                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6028                         // load it
6029                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer)))
6030                         {
6031                                 // an image loaded, make sure width and height are equal
6032                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6033                                 {
6034                                         // if this is the first image to load successfully, allocate the cubemap memory
6035                                         if (!cubemappixels && image_width >= 1)
6036                                         {
6037                                                 cubemapsize = image_width;
6038                                                 // note this clears to black, so unavailable sides are black
6039                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6040                                         }
6041                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6042                                         if (cubemappixels)
6043                                                 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);
6044                                 }
6045                                 else
6046                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6047                                 // free the image
6048                                 Mem_Free(image_buffer);
6049                         }
6050                 }
6051         }
6052         // if a cubemap loaded, upload it
6053         if (cubemappixels)
6054         {
6055                 if (developer_loading.integer)
6056                         Con_Printf("loading cubemap \"%s\"\n", basename);
6057
6058                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR, NULL);
6059                 Mem_Free(cubemappixels);
6060         }
6061         else
6062         {
6063                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6064                 if (developer_loading.integer)
6065                 {
6066                         Con_Printf("(tried tried images ");
6067                         for (j = 0;j < 3;j++)
6068                                 for (i = 0;i < 6;i++)
6069                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
6070                         Con_Print(" and was unable to find any of them).\n");
6071                 }
6072         }
6073         return cubemaptexture;
6074 }
6075
6076 rtexture_t *R_GetCubemap(const char *basename)
6077 {
6078         int i;
6079         for (i = 0;i < r_texture_numcubemaps;i++)
6080                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6081                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6082         if (i >= MAX_CUBEMAPS)
6083                 return r_texture_whitecube;
6084         r_texture_numcubemaps++;
6085         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6086         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6087         return r_texture_cubemaps[i].texture;
6088 }
6089
6090 void R_FreeCubemaps(void)
6091 {
6092         int i;
6093         for (i = 0;i < r_texture_numcubemaps;i++)
6094         {
6095                 if (developer_loading.integer)
6096                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6097                 if (r_texture_cubemaps[i].texture)
6098                         R_FreeTexture(r_texture_cubemaps[i].texture);
6099         }
6100         r_texture_numcubemaps = 0;
6101 }
6102
6103 void R_Main_FreeViewCache(void)
6104 {
6105         if (r_refdef.viewcache.entityvisible)
6106                 Mem_Free(r_refdef.viewcache.entityvisible);
6107         if (r_refdef.viewcache.world_pvsbits)
6108                 Mem_Free(r_refdef.viewcache.world_pvsbits);
6109         if (r_refdef.viewcache.world_leafvisible)
6110                 Mem_Free(r_refdef.viewcache.world_leafvisible);
6111         if (r_refdef.viewcache.world_surfacevisible)
6112                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6113         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6114 }
6115
6116 void R_Main_ResizeViewCache(void)
6117 {
6118         int numentities = r_refdef.scene.numentities;
6119         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6120         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6121         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6122         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6123         if (r_refdef.viewcache.maxentities < numentities)
6124         {
6125                 r_refdef.viewcache.maxentities = numentities;
6126                 if (r_refdef.viewcache.entityvisible)
6127                         Mem_Free(r_refdef.viewcache.entityvisible);
6128                 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6129         }
6130         if (r_refdef.viewcache.world_numclusters != numclusters)
6131         {
6132                 r_refdef.viewcache.world_numclusters = numclusters;
6133                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6134                 if (r_refdef.viewcache.world_pvsbits)
6135                         Mem_Free(r_refdef.viewcache.world_pvsbits);
6136                 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6137         }
6138         if (r_refdef.viewcache.world_numleafs != numleafs)
6139         {
6140                 r_refdef.viewcache.world_numleafs = numleafs;
6141                 if (r_refdef.viewcache.world_leafvisible)
6142                         Mem_Free(r_refdef.viewcache.world_leafvisible);
6143                 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6144         }
6145         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6146         {
6147                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6148                 if (r_refdef.viewcache.world_surfacevisible)
6149                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
6150                 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6151         }
6152 }
6153
6154 extern rtexture_t *loadingscreentexture;
6155 void gl_main_start(void)
6156 {
6157         loadingscreentexture = NULL;
6158         r_texture_blanknormalmap = NULL;
6159         r_texture_white = NULL;
6160         r_texture_grey128 = NULL;
6161         r_texture_black = NULL;
6162         r_texture_whitecube = NULL;
6163         r_texture_normalizationcube = NULL;
6164         r_texture_fogattenuation = NULL;
6165         r_texture_fogheighttexture = NULL;
6166         r_texture_gammaramps = NULL;
6167         r_texture_numcubemaps = 0;
6168
6169         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
6170         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6171
6172         switch(vid.renderpath)
6173         {
6174         case RENDERPATH_GL20:
6175         case RENDERPATH_CGGL:
6176                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6177                 Cvar_SetValueQuick(&gl_combine, 1);
6178                 Cvar_SetValueQuick(&r_glsl, 1);
6179                 r_loadnormalmap = true;
6180                 r_loadgloss = true;
6181                 r_loadfog = false;
6182                 break;
6183         case RENDERPATH_GL13:
6184                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6185                 Cvar_SetValueQuick(&gl_combine, 1);
6186                 Cvar_SetValueQuick(&r_glsl, 0);
6187                 r_loadnormalmap = false;
6188                 r_loadgloss = false;
6189                 r_loadfog = true;
6190                 break;
6191         case RENDERPATH_GL11:
6192                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6193                 Cvar_SetValueQuick(&gl_combine, 0);
6194                 Cvar_SetValueQuick(&r_glsl, 0);
6195                 r_loadnormalmap = false;
6196                 r_loadgloss = false;
6197                 r_loadfog = true;
6198                 break;
6199         }
6200
6201         R_AnimCache_Free();
6202         R_FrameData_Reset();
6203
6204         r_numqueries = 0;
6205         r_maxqueries = 0;
6206         memset(r_queries, 0, sizeof(r_queries));
6207
6208         r_qwskincache = NULL;
6209         r_qwskincache_size = 0;
6210
6211         // set up r_skinframe loading system for textures
6212         memset(&r_skinframe, 0, sizeof(r_skinframe));
6213         r_skinframe.loadsequence = 1;
6214         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
6215
6216         r_main_texturepool = R_AllocTexturePool();
6217         R_BuildBlankTextures();
6218         R_BuildNoTexture();
6219         if (vid.support.arb_texture_cube_map)
6220         {
6221                 R_BuildWhiteCube();
6222                 R_BuildNormalizationCube();
6223         }
6224         r_texture_fogattenuation = NULL;
6225         r_texture_fogheighttexture = NULL;
6226         r_texture_gammaramps = NULL;
6227         //r_texture_fogintensity = NULL;
6228         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6229         memset(&r_waterstate, 0, sizeof(r_waterstate));
6230         r_glsl_permutation = NULL;
6231         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6232         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
6233         glslshaderstring = NULL;
6234 #ifdef SUPPORTCG
6235         r_cg_permutation = NULL;
6236         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
6237         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
6238         cgshaderstring = NULL;
6239 #endif
6240         memset(&r_svbsp, 0, sizeof (r_svbsp));
6241
6242         r_refdef.fogmasktable_density = 0;
6243 }
6244
6245 void gl_main_shutdown(void)
6246 {
6247         R_AnimCache_Free();
6248         R_FrameData_Reset();
6249
6250         R_Main_FreeViewCache();
6251
6252         if (r_maxqueries)
6253                 qglDeleteQueriesARB(r_maxqueries, r_queries);
6254
6255         r_numqueries = 0;
6256         r_maxqueries = 0;
6257         memset(r_queries, 0, sizeof(r_queries));
6258
6259         r_qwskincache = NULL;
6260         r_qwskincache_size = 0;
6261
6262         // clear out the r_skinframe state
6263         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
6264         memset(&r_skinframe, 0, sizeof(r_skinframe));
6265
6266         if (r_svbsp.nodes)
6267                 Mem_Free(r_svbsp.nodes);
6268         memset(&r_svbsp, 0, sizeof (r_svbsp));
6269         R_FreeTexturePool(&r_main_texturepool);
6270         loadingscreentexture = NULL;
6271         r_texture_blanknormalmap = NULL;
6272         r_texture_white = NULL;
6273         r_texture_grey128 = NULL;
6274         r_texture_black = NULL;
6275         r_texture_whitecube = NULL;
6276         r_texture_normalizationcube = NULL;
6277         r_texture_fogattenuation = NULL;
6278         r_texture_fogheighttexture = NULL;
6279         r_texture_gammaramps = NULL;
6280         r_texture_numcubemaps = 0;
6281         //r_texture_fogintensity = NULL;
6282         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6283         memset(&r_waterstate, 0, sizeof(r_waterstate));
6284         r_glsl_permutation = NULL;
6285         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6286         glslshaderstring = NULL;
6287 #ifdef SUPPORTCG
6288         r_cg_permutation = NULL;
6289         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
6290         cgshaderstring = NULL;
6291 #endif
6292         R_GLSL_Restart_f();
6293 }
6294
6295 extern void CL_ParseEntityLump(char *entitystring);
6296 void gl_main_newmap(void)
6297 {
6298         // FIXME: move this code to client
6299         int l;
6300         char *entities, entname[MAX_QPATH];
6301         if (r_qwskincache)
6302                 Mem_Free(r_qwskincache);
6303         r_qwskincache = NULL;
6304         r_qwskincache_size = 0;
6305         if (cl.worldmodel)
6306         {
6307                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
6308                 l = (int)strlen(entname) - 4;
6309                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
6310                 {
6311                         memcpy(entname + l, ".ent", 5);
6312                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
6313                         {
6314                                 CL_ParseEntityLump(entities);
6315                                 Mem_Free(entities);
6316                                 return;
6317                         }
6318                 }
6319                 if (cl.worldmodel->brush.entities)
6320                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
6321         }
6322         R_Main_FreeViewCache();
6323
6324         R_FrameData_Reset();
6325 }
6326
6327 void GL_Main_Init(void)
6328 {
6329         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
6330
6331         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
6332         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
6333         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
6334         if (gamemode == GAME_NEHAHRA)
6335         {
6336                 Cvar_RegisterVariable (&gl_fogenable);
6337                 Cvar_RegisterVariable (&gl_fogdensity);
6338                 Cvar_RegisterVariable (&gl_fogred);
6339                 Cvar_RegisterVariable (&gl_foggreen);
6340                 Cvar_RegisterVariable (&gl_fogblue);
6341                 Cvar_RegisterVariable (&gl_fogstart);
6342                 Cvar_RegisterVariable (&gl_fogend);
6343                 Cvar_RegisterVariable (&gl_skyclip);
6344         }
6345         Cvar_RegisterVariable(&r_motionblur);
6346         Cvar_RegisterVariable(&r_motionblur_maxblur);
6347         Cvar_RegisterVariable(&r_motionblur_bmin);
6348         Cvar_RegisterVariable(&r_motionblur_vmin);
6349         Cvar_RegisterVariable(&r_motionblur_vmax);
6350         Cvar_RegisterVariable(&r_motionblur_vcoeff);
6351         Cvar_RegisterVariable(&r_motionblur_randomize);
6352         Cvar_RegisterVariable(&r_damageblur);
6353         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
6354         Cvar_RegisterVariable(&r_equalize_entities_minambient);
6355         Cvar_RegisterVariable(&r_equalize_entities_by);
6356         Cvar_RegisterVariable(&r_equalize_entities_to);
6357         Cvar_RegisterVariable(&r_depthfirst);
6358         Cvar_RegisterVariable(&r_useinfinitefarclip);
6359         Cvar_RegisterVariable(&r_farclip_base);
6360         Cvar_RegisterVariable(&r_farclip_world);
6361         Cvar_RegisterVariable(&r_nearclip);
6362         Cvar_RegisterVariable(&r_showbboxes);
6363         Cvar_RegisterVariable(&r_showsurfaces);
6364         Cvar_RegisterVariable(&r_showtris);
6365         Cvar_RegisterVariable(&r_shownormals);
6366         Cvar_RegisterVariable(&r_showlighting);
6367         Cvar_RegisterVariable(&r_showshadowvolumes);
6368         Cvar_RegisterVariable(&r_showcollisionbrushes);
6369         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
6370         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
6371         Cvar_RegisterVariable(&r_showdisabledepthtest);
6372         Cvar_RegisterVariable(&r_drawportals);
6373         Cvar_RegisterVariable(&r_drawentities);
6374         Cvar_RegisterVariable(&r_cullentities_trace);
6375         Cvar_RegisterVariable(&r_cullentities_trace_samples);
6376         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
6377         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
6378         Cvar_RegisterVariable(&r_cullentities_trace_delay);
6379         Cvar_RegisterVariable(&r_drawviewmodel);
6380         Cvar_RegisterVariable(&r_drawexteriormodel);
6381         Cvar_RegisterVariable(&r_speeds);
6382         Cvar_RegisterVariable(&r_fullbrights);
6383         Cvar_RegisterVariable(&r_wateralpha);
6384         Cvar_RegisterVariable(&r_dynamic);
6385         Cvar_RegisterVariable(&r_fullbright);
6386         Cvar_RegisterVariable(&r_shadows);
6387         Cvar_RegisterVariable(&r_shadows_darken);
6388         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
6389         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
6390         Cvar_RegisterVariable(&r_shadows_throwdistance);
6391         Cvar_RegisterVariable(&r_shadows_throwdirection);
6392         Cvar_RegisterVariable(&r_shadows_focus);
6393         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
6394         Cvar_RegisterVariable(&r_q1bsp_skymasking);
6395         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
6396         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
6397         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
6398         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
6399         Cvar_RegisterVariable(&r_fog_exp2);
6400         Cvar_RegisterVariable(&r_drawfog);
6401         Cvar_RegisterVariable(&r_transparentdepthmasking);
6402         Cvar_RegisterVariable(&r_texture_dds_load);
6403         Cvar_RegisterVariable(&r_texture_dds_save);
6404         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
6405         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
6406         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
6407         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
6408         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
6409         Cvar_RegisterVariable(&r_textureunits);
6410         Cvar_RegisterVariable(&gl_combine);
6411         Cvar_RegisterVariable(&r_glsl);
6412         Cvar_RegisterVariable(&r_glsl_deluxemapping);
6413         Cvar_RegisterVariable(&r_glsl_offsetmapping);
6414         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
6415         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
6416         Cvar_RegisterVariable(&r_glsl_postprocess);
6417         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
6418         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
6419         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
6420         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
6421         Cvar_RegisterVariable(&r_water);
6422         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
6423         Cvar_RegisterVariable(&r_water_clippingplanebias);
6424         Cvar_RegisterVariable(&r_water_refractdistort);
6425         Cvar_RegisterVariable(&r_water_reflectdistort);
6426         Cvar_RegisterVariable(&r_lerpsprites);
6427         Cvar_RegisterVariable(&r_lerpmodels);
6428         Cvar_RegisterVariable(&r_lerplightstyles);
6429         Cvar_RegisterVariable(&r_waterscroll);
6430         Cvar_RegisterVariable(&r_bloom);
6431         Cvar_RegisterVariable(&r_bloom_colorscale);
6432         Cvar_RegisterVariable(&r_bloom_brighten);
6433         Cvar_RegisterVariable(&r_bloom_blur);
6434         Cvar_RegisterVariable(&r_bloom_resolution);
6435         Cvar_RegisterVariable(&r_bloom_colorexponent);
6436         Cvar_RegisterVariable(&r_bloom_colorsubtract);
6437         Cvar_RegisterVariable(&r_hdr);
6438         Cvar_RegisterVariable(&r_hdr_scenebrightness);
6439         Cvar_RegisterVariable(&r_hdr_glowintensity);
6440         Cvar_RegisterVariable(&r_hdr_range);
6441         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
6442         Cvar_RegisterVariable(&developer_texturelogging);
6443         Cvar_RegisterVariable(&gl_lightmaps);
6444         Cvar_RegisterVariable(&r_test);
6445         Cvar_RegisterVariable(&r_glsl_saturation);
6446         Cvar_RegisterVariable(&r_framedatasize);
6447         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
6448                 Cvar_SetValue("r_fullbrights", 0);
6449         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
6450
6451         Cvar_RegisterVariable(&r_track_sprites);
6452         Cvar_RegisterVariable(&r_track_sprites_flags);
6453         Cvar_RegisterVariable(&r_track_sprites_scalew);
6454         Cvar_RegisterVariable(&r_track_sprites_scaleh);
6455         Cvar_RegisterVariable(&r_overheadsprites_perspective);
6456         Cvar_RegisterVariable(&r_overheadsprites_pushback);
6457 }
6458
6459 extern void R_Textures_Init(void);
6460 extern void GL_Draw_Init(void);
6461 extern void GL_Main_Init(void);
6462 extern void R_Shadow_Init(void);
6463 extern void R_Sky_Init(void);
6464 extern void GL_Surf_Init(void);
6465 extern void R_Particles_Init(void);
6466 extern void R_Explosion_Init(void);
6467 extern void gl_backend_init(void);
6468 extern void Sbar_Init(void);
6469 extern void R_LightningBeams_Init(void);
6470 extern void Mod_RenderInit(void);
6471 extern void Font_Init(void);
6472
6473 void Render_Init(void)
6474 {
6475         gl_backend_init();
6476         R_Textures_Init();
6477         GL_Main_Init();
6478         Font_Init();
6479         GL_Draw_Init();
6480         R_Shadow_Init();
6481         R_Sky_Init();
6482         GL_Surf_Init();
6483         Sbar_Init();
6484         R_Particles_Init();
6485         R_Explosion_Init();
6486         R_LightningBeams_Init();
6487         Mod_RenderInit();
6488 }
6489
6490 /*
6491 ===============
6492 GL_Init
6493 ===============
6494 */
6495 extern char *ENGINE_EXTENSIONS;
6496 void GL_Init (void)
6497 {
6498         gl_renderer = (const char *)qglGetString(GL_RENDERER);
6499         gl_vendor = (const char *)qglGetString(GL_VENDOR);
6500         gl_version = (const char *)qglGetString(GL_VERSION);
6501         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
6502
6503         if (!gl_extensions)
6504                 gl_extensions = "";
6505         if (!gl_platformextensions)
6506                 gl_platformextensions = "";
6507
6508         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
6509         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
6510         Con_Printf("GL_VERSION: %s\n", gl_version);
6511         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
6512         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
6513
6514         VID_CheckExtensions();
6515
6516         // LordHavoc: report supported extensions
6517         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
6518
6519         // clear to black (loading plaque will be seen over this)
6520         CHECKGLERROR
6521         qglClearColor(0,0,0,1);CHECKGLERROR
6522         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
6523 }
6524
6525 int R_CullBox(const vec3_t mins, const vec3_t maxs)
6526 {
6527         int i;
6528         mplane_t *p;
6529         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6530         {
6531                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
6532                 if (i == 4)
6533                         continue;
6534                 p = r_refdef.view.frustum + i;
6535                 switch(p->signbits)
6536                 {
6537                 default:
6538                 case 0:
6539                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6540                                 return true;
6541                         break;
6542                 case 1:
6543                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6544                                 return true;
6545                         break;
6546                 case 2:
6547                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6548                                 return true;
6549                         break;
6550                 case 3:
6551                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6552                                 return true;
6553                         break;
6554                 case 4:
6555                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6556                                 return true;
6557                         break;
6558                 case 5:
6559                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6560                                 return true;
6561                         break;
6562                 case 6:
6563                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6564                                 return true;
6565                         break;
6566                 case 7:
6567                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6568                                 return true;
6569                         break;
6570                 }
6571         }
6572         return false;
6573 }
6574
6575 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
6576 {
6577         int i;
6578         const mplane_t *p;
6579         for (i = 0;i < numplanes;i++)
6580         {
6581                 p = planes + i;
6582                 switch(p->signbits)
6583                 {
6584                 default:
6585                 case 0:
6586                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6587                                 return true;
6588                         break;
6589                 case 1:
6590                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6591                                 return true;
6592                         break;
6593                 case 2:
6594                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6595                                 return true;
6596                         break;
6597                 case 3:
6598                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6599                                 return true;
6600                         break;
6601                 case 4:
6602                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6603                                 return true;
6604                         break;
6605                 case 5:
6606                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6607                                 return true;
6608                         break;
6609                 case 6:
6610                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6611                                 return true;
6612                         break;
6613                 case 7:
6614                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6615                                 return true;
6616                         break;
6617                 }
6618         }
6619         return false;
6620 }
6621
6622 //==================================================================================
6623
6624 // LordHavoc: this stores temporary data used within the same frame
6625
6626 qboolean r_framedata_failed;
6627 static size_t r_framedata_size;
6628 static size_t r_framedata_current;
6629 static void *r_framedata_base;
6630
6631 void R_FrameData_Reset(void)
6632 {
6633         if (r_framedata_base)
6634                 Mem_Free(r_framedata_base);
6635         r_framedata_base = NULL;
6636         r_framedata_size = 0;
6637         r_framedata_current = 0;
6638         r_framedata_failed = false;
6639 }
6640
6641 void R_FrameData_NewFrame(void)
6642 {
6643         size_t wantedsize;
6644         if (r_framedata_failed)
6645                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
6646         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
6647         wantedsize = bound(65536, wantedsize, 128*1024*1024);
6648         if (r_framedata_size != wantedsize)
6649         {
6650                 r_framedata_size = wantedsize;
6651                 if (r_framedata_base)
6652                         Mem_Free(r_framedata_base);
6653                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
6654         }
6655         r_framedata_current = 0;
6656         r_framedata_failed = false;
6657 }
6658
6659 void *R_FrameData_Alloc(size_t size)
6660 {
6661         void *data;
6662
6663         // align to 16 byte boundary
6664         size = (size + 15) & ~15;
6665         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
6666         r_framedata_current += size;
6667
6668         // check overflow
6669         if (r_framedata_current > r_framedata_size)
6670                 r_framedata_failed = true;
6671
6672         // return NULL on everything after a failure
6673         if (r_framedata_failed)
6674                 return NULL;
6675
6676         return data;
6677 }
6678
6679 void *R_FrameData_Store(size_t size, void *data)
6680 {
6681         void *d = R_FrameData_Alloc(size);
6682         if (d)
6683                 memcpy(d, data, size);
6684         return d;
6685 }
6686
6687 //==================================================================================
6688
6689 // LordHavoc: animcache originally written by Echon, rewritten since then
6690
6691 /**
6692  * Animation cache prevents re-generating mesh data for an animated model
6693  * multiple times in one frame for lighting, shadowing, reflections, etc.
6694  */
6695
6696 void R_AnimCache_Free(void)
6697 {
6698 }
6699
6700 void R_AnimCache_ClearCache(void)
6701 {
6702         int i;
6703         entity_render_t *ent;
6704
6705         for (i = 0;i < r_refdef.scene.numentities;i++)
6706         {
6707                 ent = r_refdef.scene.entities[i];
6708                 ent->animcache_vertex3f = NULL;
6709                 ent->animcache_normal3f = NULL;
6710                 ent->animcache_svector3f = NULL;
6711                 ent->animcache_tvector3f = NULL;
6712                 ent->animcache_vertexposition = NULL;
6713                 ent->animcache_vertexmesh = NULL;
6714                 ent->animcache_vertexpositionbuffer = NULL;
6715                 ent->animcache_vertexmeshbuffer = NULL;
6716         }
6717 }
6718
6719 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
6720 {
6721         int i;
6722         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
6723                 ent->animcache_vertexmesh = R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
6724         if (!ent->animcache_vertexposition)
6725                 ent->animcache_vertexposition = R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
6726         if (ent->animcache_vertexposition)
6727         {
6728                 for (i = 0;i < numvertices;i++)
6729                         VectorCopy(ent->animcache_vertex3f + 3*i, ent->animcache_vertexposition[i].vertex3f);
6730                 // TODO: upload vertex buffer?
6731         }
6732         if (ent->animcache_vertexmesh)
6733         {
6734                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
6735                 for (i = 0;i < numvertices;i++)
6736                         VectorCopy(ent->animcache_vertex3f + 3*i, ent->animcache_vertexmesh[i].vertex3f);
6737                 if (ent->animcache_svector3f)
6738                         for (i = 0;i < numvertices;i++)
6739                                 VectorCopy(ent->animcache_svector3f + 3*i, ent->animcache_vertexmesh[i].svector3f);
6740                 if (ent->animcache_tvector3f)
6741                         for (i = 0;i < numvertices;i++)
6742                                 VectorCopy(ent->animcache_tvector3f + 3*i, ent->animcache_vertexmesh[i].tvector3f);
6743                 if (ent->animcache_normal3f)
6744                         for (i = 0;i < numvertices;i++)
6745                                 VectorCopy(ent->animcache_normal3f + 3*i, ent->animcache_vertexmesh[i].normal3f);
6746                 // TODO: upload vertex buffer?
6747         }
6748 }
6749
6750 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6751 {
6752         dp_model_t *model = ent->model;
6753         int numvertices;
6754         // see if it's already cached this frame
6755         if (ent->animcache_vertex3f)
6756         {
6757                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
6758                 if (wantnormals || wanttangents)
6759                 {
6760                         if (ent->animcache_normal3f)
6761                                 wantnormals = false;
6762                         if (ent->animcache_svector3f)
6763                                 wanttangents = false;
6764                         if (wantnormals || wanttangents)
6765                         {
6766                                 numvertices = model->surfmesh.num_vertices;
6767                                 if (wantnormals)
6768                                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6769                                 if (wanttangents)
6770                                 {
6771                                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6772                                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6773                                 }
6774                                 if (!r_framedata_failed)
6775                                 {
6776                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
6777                                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
6778                                 }
6779                         }
6780                 }
6781         }
6782         else
6783         {
6784                 // see if this ent is worth caching
6785                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
6786                         return false;
6787                 // get some memory for this entity and generate mesh data
6788                 numvertices = model->surfmesh.num_vertices;
6789                 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6790                 if (wantnormals)
6791                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6792                 if (wanttangents)
6793                 {
6794                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6795                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6796                 }
6797                 if (!r_framedata_failed)
6798                 {
6799                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
6800                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
6801                 }
6802         }
6803         return !r_framedata_failed;
6804 }
6805
6806 void R_AnimCache_CacheVisibleEntities(void)
6807 {
6808         int i;
6809         qboolean wantnormals = true;
6810         qboolean wanttangents = !r_showsurfaces.integer;
6811
6812         switch(vid.renderpath)
6813         {
6814         case RENDERPATH_GL20:
6815         case RENDERPATH_CGGL:
6816                 break;
6817         case RENDERPATH_GL13:
6818         case RENDERPATH_GL11:
6819                 wanttangents = false;
6820                 break;
6821         }
6822
6823         if (r_shownormals.integer)
6824                 wanttangents = wantnormals = true;
6825
6826         // TODO: thread this
6827         // NOTE: R_PrepareRTLights() also caches entities
6828
6829         for (i = 0;i < r_refdef.scene.numentities;i++)
6830                 if (r_refdef.viewcache.entityvisible[i])
6831                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
6832 }
6833
6834 //==================================================================================
6835
6836 static void R_View_UpdateEntityLighting (void)
6837 {
6838         int i;
6839         entity_render_t *ent;
6840         vec3_t tempdiffusenormal, avg;
6841         vec_t f, fa, fd, fdd;
6842         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
6843
6844         for (i = 0;i < r_refdef.scene.numentities;i++)
6845         {
6846                 ent = r_refdef.scene.entities[i];
6847
6848                 // skip unseen models
6849                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
6850                         continue;
6851
6852                 // skip bsp models
6853                 if (ent->model && ent->model->brush.num_leafs)
6854                 {
6855                         // TODO: use modellight for r_ambient settings on world?
6856                         VectorSet(ent->modellight_ambient, 0, 0, 0);
6857                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
6858                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
6859                         continue;
6860                 }
6861
6862                 // fetch the lighting from the worldmodel data
6863                 VectorClear(ent->modellight_ambient);
6864                 VectorClear(ent->modellight_diffuse);
6865                 VectorClear(tempdiffusenormal);
6866                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
6867                 {
6868                         vec3_t org;
6869                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6870                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
6871                         if(ent->flags & RENDER_EQUALIZE)
6872                         {
6873                                 // first fix up ambient lighting...
6874                                 if(r_equalize_entities_minambient.value > 0)
6875                                 {
6876                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
6877                                         if(fd > 0)
6878                                         {
6879                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
6880                                                 if(fa < r_equalize_entities_minambient.value * fd)
6881                                                 {
6882                                                         // solve:
6883                                                         //   fa'/fd' = minambient
6884                                                         //   fa'+0.25*fd' = fa+0.25*fd
6885                                                         //   ...
6886                                                         //   fa' = fd' * minambient
6887                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
6888                                                         //   ...
6889                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
6890                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
6891                                                         //   ...
6892                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
6893                                                         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
6894                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
6895                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6896                                                 }
6897                                         }
6898                                 }
6899
6900                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
6901                                 {
6902                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
6903                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
6904                                         if(f > 0)
6905                                         {
6906                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
6907                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
6908                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6909                                         }
6910                                 }
6911                         }
6912                 }
6913                 else // highly rare
6914                         VectorSet(ent->modellight_ambient, 1, 1, 1);
6915
6916                 // move the light direction into modelspace coordinates for lighting code
6917                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
6918                 if(VectorLength2(ent->modellight_lightdir) == 0)
6919                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
6920                 VectorNormalize(ent->modellight_lightdir);
6921         }
6922 }
6923
6924 #define MAX_LINEOFSIGHTTRACES 64
6925
6926 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
6927 {
6928         int i;
6929         vec3_t boxmins, boxmaxs;
6930         vec3_t start;
6931         vec3_t end;
6932         dp_model_t *model = r_refdef.scene.worldmodel;
6933
6934         if (!model || !model->brush.TraceLineOfSight)
6935                 return true;
6936
6937         // expand the box a little
6938         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
6939         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
6940         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
6941         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
6942         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
6943         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
6944
6945         // return true if eye is inside enlarged box
6946         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
6947                 return true;
6948
6949         // try center
6950         VectorCopy(eye, start);
6951         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
6952         if (model->brush.TraceLineOfSight(model, start, end))
6953                 return true;
6954
6955         // try various random positions
6956         for (i = 0;i < numsamples;i++)
6957         {
6958                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
6959                 if (model->brush.TraceLineOfSight(model, start, end))
6960                         return true;
6961         }
6962
6963         return false;
6964 }
6965
6966
6967 static void R_View_UpdateEntityVisible (void)
6968 {
6969         int i;
6970         int renderimask;
6971         int samples;
6972         entity_render_t *ent;
6973
6974         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
6975                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
6976                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
6977                 :                                                          RENDER_EXTERIORMODEL;
6978         if (!r_drawviewmodel.integer)
6979                 renderimask |= RENDER_VIEWMODEL;
6980         if (!r_drawexteriormodel.integer)
6981                 renderimask |= RENDER_EXTERIORMODEL;
6982         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
6983         {
6984                 // worldmodel can check visibility
6985                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
6986                 for (i = 0;i < r_refdef.scene.numentities;i++)
6987                 {
6988                         ent = r_refdef.scene.entities[i];
6989                         if (!(ent->flags & renderimask))
6990                         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)))
6991                         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))
6992                                 r_refdef.viewcache.entityvisible[i] = true;
6993                 }
6994                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
6995                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
6996                 {
6997                         for (i = 0;i < r_refdef.scene.numentities;i++)
6998                         {
6999                                 ent = r_refdef.scene.entities[i];
7000                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
7001                                 {
7002                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
7003                                         if (samples < 0)
7004                                                 continue; // temp entities do pvs only
7005                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
7006                                                 ent->last_trace_visibility = realtime;
7007                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
7008                                                 r_refdef.viewcache.entityvisible[i] = 0;
7009                                 }
7010                         }
7011                 }
7012         }
7013         else
7014         {
7015                 // no worldmodel or it can't check visibility
7016                 for (i = 0;i < r_refdef.scene.numentities;i++)
7017                 {
7018                         ent = r_refdef.scene.entities[i];
7019                         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));
7020                 }
7021         }
7022 }
7023
7024 /// only used if skyrendermasked, and normally returns false
7025 int R_DrawBrushModelsSky (void)
7026 {
7027         int i, sky;
7028         entity_render_t *ent;
7029
7030         sky = false;
7031         for (i = 0;i < r_refdef.scene.numentities;i++)
7032         {
7033                 if (!r_refdef.viewcache.entityvisible[i])
7034                         continue;
7035                 ent = r_refdef.scene.entities[i];
7036                 if (!ent->model || !ent->model->DrawSky)
7037                         continue;
7038                 ent->model->DrawSky(ent);
7039                 sky = true;
7040         }
7041         return sky;
7042 }
7043
7044 static void R_DrawNoModel(entity_render_t *ent);
7045 static void R_DrawModels(void)
7046 {
7047         int i;
7048         entity_render_t *ent;
7049
7050         for (i = 0;i < r_refdef.scene.numentities;i++)
7051         {
7052                 if (!r_refdef.viewcache.entityvisible[i])
7053                         continue;
7054                 ent = r_refdef.scene.entities[i];
7055                 r_refdef.stats.entities++;
7056                 if (ent->model && ent->model->Draw != NULL)
7057                         ent->model->Draw(ent);
7058                 else
7059                         R_DrawNoModel(ent);
7060         }
7061 }
7062
7063 static void R_DrawModelsDepth(void)
7064 {
7065         int i;
7066         entity_render_t *ent;
7067
7068         for (i = 0;i < r_refdef.scene.numentities;i++)
7069         {
7070                 if (!r_refdef.viewcache.entityvisible[i])
7071                         continue;
7072                 ent = r_refdef.scene.entities[i];
7073                 if (ent->model && ent->model->DrawDepth != NULL)
7074                         ent->model->DrawDepth(ent);
7075         }
7076 }
7077
7078 static void R_DrawModelsDebug(void)
7079 {
7080         int i;
7081         entity_render_t *ent;
7082
7083         for (i = 0;i < r_refdef.scene.numentities;i++)
7084         {
7085                 if (!r_refdef.viewcache.entityvisible[i])
7086                         continue;
7087                 ent = r_refdef.scene.entities[i];
7088                 if (ent->model && ent->model->DrawDebug != NULL)
7089                         ent->model->DrawDebug(ent);
7090         }
7091 }
7092
7093 static void R_DrawModelsAddWaterPlanes(void)
7094 {
7095         int i;
7096         entity_render_t *ent;
7097
7098         for (i = 0;i < r_refdef.scene.numentities;i++)
7099         {
7100                 if (!r_refdef.viewcache.entityvisible[i])
7101                         continue;
7102                 ent = r_refdef.scene.entities[i];
7103                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
7104                         ent->model->DrawAddWaterPlanes(ent);
7105         }
7106 }
7107
7108 static void R_View_SetFrustum(void)
7109 {
7110         int i;
7111         double slopex, slopey;
7112         vec3_t forward, left, up, origin;
7113
7114         // we can't trust r_refdef.view.forward and friends in reflected scenes
7115         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
7116
7117 #if 0
7118         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
7119         r_refdef.view.frustum[0].normal[1] = 0 - 0;
7120         r_refdef.view.frustum[0].normal[2] = -1 - 0;
7121         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
7122         r_refdef.view.frustum[1].normal[1] = 0 + 0;
7123         r_refdef.view.frustum[1].normal[2] = -1 + 0;
7124         r_refdef.view.frustum[2].normal[0] = 0 - 0;
7125         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
7126         r_refdef.view.frustum[2].normal[2] = -1 - 0;
7127         r_refdef.view.frustum[3].normal[0] = 0 + 0;
7128         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
7129         r_refdef.view.frustum[3].normal[2] = -1 + 0;
7130 #endif
7131
7132 #if 0
7133         zNear = r_refdef.nearclip;
7134         nudge = 1.0 - 1.0 / (1<<23);
7135         r_refdef.view.frustum[4].normal[0] = 0 - 0;
7136         r_refdef.view.frustum[4].normal[1] = 0 - 0;
7137         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
7138         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
7139         r_refdef.view.frustum[5].normal[0] = 0 + 0;
7140         r_refdef.view.frustum[5].normal[1] = 0 + 0;
7141         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
7142         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
7143 #endif
7144
7145
7146
7147 #if 0
7148         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
7149         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
7150         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
7151         r_refdef.view.frustum[0].dist = m[15] - m[12];
7152
7153         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
7154         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
7155         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
7156         r_refdef.view.frustum[1].dist = m[15] + m[12];
7157
7158         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
7159         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
7160         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
7161         r_refdef.view.frustum[2].dist = m[15] - m[13];
7162
7163         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
7164         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
7165         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
7166         r_refdef.view.frustum[3].dist = m[15] + m[13];
7167
7168         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
7169         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
7170         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
7171         r_refdef.view.frustum[4].dist = m[15] - m[14];
7172
7173         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
7174         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
7175         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
7176         r_refdef.view.frustum[5].dist = m[15] + m[14];
7177 #endif
7178
7179         if (r_refdef.view.useperspective)
7180         {
7181                 slopex = 1.0 / r_refdef.view.frustum_x;
7182                 slopey = 1.0 / r_refdef.view.frustum_y;
7183                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
7184                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
7185                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
7186                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
7187                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7188
7189                 // Leaving those out was a mistake, those were in the old code, and they
7190                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
7191                 // I couldn't reproduce it after adding those normalizations. --blub
7192                 VectorNormalize(r_refdef.view.frustum[0].normal);
7193                 VectorNormalize(r_refdef.view.frustum[1].normal);
7194                 VectorNormalize(r_refdef.view.frustum[2].normal);
7195                 VectorNormalize(r_refdef.view.frustum[3].normal);
7196
7197                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
7198                 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]);
7199                 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]);
7200                 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]);
7201                 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]);
7202
7203                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
7204                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
7205                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
7206                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
7207                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7208         }
7209         else
7210         {
7211                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
7212                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
7213                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
7214                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
7215                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7216                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
7217                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
7218                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
7219                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
7220                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7221         }
7222         r_refdef.view.numfrustumplanes = 5;
7223
7224         if (r_refdef.view.useclipplane)
7225         {
7226                 r_refdef.view.numfrustumplanes = 6;
7227                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
7228         }
7229
7230         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7231                 PlaneClassify(r_refdef.view.frustum + i);
7232
7233         // LordHavoc: note to all quake engine coders, Quake had a special case
7234         // for 90 degrees which assumed a square view (wrong), so I removed it,
7235         // Quake2 has it disabled as well.
7236
7237         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
7238         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
7239         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
7240         //PlaneClassify(&frustum[0]);
7241
7242         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
7243         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
7244         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
7245         //PlaneClassify(&frustum[1]);
7246
7247         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
7248         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
7249         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
7250         //PlaneClassify(&frustum[2]);
7251
7252         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
7253         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
7254         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
7255         //PlaneClassify(&frustum[3]);
7256
7257         // nearclip plane
7258         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
7259         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
7260         //PlaneClassify(&frustum[4]);
7261 }
7262
7263 void R_View_Update(void)
7264 {
7265         R_Main_ResizeViewCache();
7266         R_View_SetFrustum();
7267         R_View_WorldVisibility(r_refdef.view.useclipplane);
7268         R_View_UpdateEntityVisible();
7269         R_View_UpdateEntityLighting();
7270 }
7271
7272 void R_SetupView(qboolean allowwaterclippingplane)
7273 {
7274         const float *customclipplane = NULL;
7275         float plane[4];
7276         if (r_refdef.view.useclipplane && allowwaterclippingplane)
7277         {
7278                 // LordHavoc: couldn't figure out how to make this approach the
7279                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
7280                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
7281                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
7282                         dist = r_refdef.view.clipplane.dist;
7283                 plane[0] = r_refdef.view.clipplane.normal[0];
7284                 plane[1] = r_refdef.view.clipplane.normal[1];
7285                 plane[2] = r_refdef.view.clipplane.normal[2];
7286                 plane[3] = dist;
7287                 customclipplane = plane;
7288         }
7289
7290         if (!r_refdef.view.useperspective)
7291                 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);
7292         else if (vid.stencil && r_useinfinitefarclip.integer)
7293                 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);
7294         else
7295                 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);
7296         R_SetViewport(&r_refdef.view.viewport);
7297 }
7298
7299 void R_EntityMatrix(const matrix4x4_t *matrix)
7300 {
7301         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
7302         {
7303                 gl_modelmatrixchanged = false;
7304                 gl_modelmatrix = *matrix;
7305                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
7306                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
7307                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
7308                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
7309                 CHECKGLERROR
7310                 switch(vid.renderpath)
7311                 {
7312                 case RENDERPATH_GL20:
7313                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
7314                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
7315                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7316                         break;
7317                 case RENDERPATH_CGGL:
7318 #ifdef SUPPORTCG
7319                         CHECKCGERROR
7320                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
7321                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
7322                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7323 #endif
7324                         break;
7325                 case RENDERPATH_GL13:
7326                 case RENDERPATH_GL11:
7327                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7328                         break;
7329                 }
7330         }
7331 }
7332
7333 void R_ResetViewRendering2D(void)
7334 {
7335         r_viewport_t viewport;
7336         DrawQ_Finish();
7337
7338         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
7339         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);
7340         R_SetViewport(&viewport);
7341         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
7342         GL_Color(1, 1, 1, 1);
7343         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7344         GL_BlendFunc(GL_ONE, GL_ZERO);
7345         GL_AlphaTest(false);
7346         GL_ScissorTest(false);
7347         GL_DepthMask(false);
7348         GL_DepthRange(0, 1);
7349         GL_DepthTest(false);
7350         R_EntityMatrix(&identitymatrix);
7351         R_Mesh_ResetTextureState();
7352         GL_PolygonOffset(0, 0);
7353         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7354         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7355         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7356         qglStencilMask(~0);CHECKGLERROR
7357         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7358         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7359         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
7360 }
7361
7362 void R_ResetViewRendering3D(void)
7363 {
7364         DrawQ_Finish();
7365
7366         R_SetupView(true);
7367         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7368         GL_Color(1, 1, 1, 1);
7369         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7370         GL_BlendFunc(GL_ONE, GL_ZERO);
7371         GL_AlphaTest(false);
7372         GL_ScissorTest(true);
7373         GL_DepthMask(true);
7374         GL_DepthRange(0, 1);
7375         GL_DepthTest(true);
7376         R_EntityMatrix(&identitymatrix);
7377         R_Mesh_ResetTextureState();
7378         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7379         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7380         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7381         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7382         qglStencilMask(~0);CHECKGLERROR
7383         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7384         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7385         GL_CullFace(r_refdef.view.cullface_back);
7386 }
7387
7388 /*
7389 ================
7390 R_RenderView_UpdateViewVectors
7391 ================
7392 */
7393 static void R_RenderView_UpdateViewVectors(void)
7394 {
7395         // break apart the view matrix into vectors for various purposes
7396         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
7397         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
7398         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
7399         VectorNegate(r_refdef.view.left, r_refdef.view.right);
7400         // make an inverted copy of the view matrix for tracking sprites
7401         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
7402 }
7403
7404 void R_RenderScene(void);
7405 void R_RenderWaterPlanes(void);
7406
7407 static void R_Water_StartFrame(void)
7408 {
7409         int i;
7410         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
7411         r_waterstate_waterplane_t *p;
7412
7413         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
7414                 return;
7415
7416         switch(vid.renderpath)
7417         {
7418         case RENDERPATH_GL20:
7419         case RENDERPATH_CGGL:
7420                 break;
7421         case RENDERPATH_GL13:
7422         case RENDERPATH_GL11:
7423                 return;
7424         }
7425
7426         // set waterwidth and waterheight to the water resolution that will be
7427         // used (often less than the screen resolution for faster rendering)
7428         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
7429         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
7430
7431         // calculate desired texture sizes
7432         // can't use water if the card does not support the texture size
7433         if (!r_water.integer || r_showsurfaces.integer)
7434                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
7435         else if (vid.support.arb_texture_non_power_of_two)
7436         {
7437                 texturewidth = waterwidth;
7438                 textureheight = waterheight;
7439                 camerawidth = waterwidth;
7440                 cameraheight = waterheight;
7441         }
7442         else
7443         {
7444                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
7445                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
7446                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
7447                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
7448         }
7449
7450         // allocate textures as needed
7451         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
7452         {
7453                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7454                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
7455                 {
7456                         if (p->texture_refraction)
7457                                 R_FreeTexture(p->texture_refraction);
7458                         p->texture_refraction = NULL;
7459                         if (p->texture_reflection)
7460                                 R_FreeTexture(p->texture_reflection);
7461                         p->texture_reflection = NULL;
7462                         if (p->texture_camera)
7463                                 R_FreeTexture(p->texture_camera);
7464                         p->texture_camera = NULL;
7465                 }
7466                 memset(&r_waterstate, 0, sizeof(r_waterstate));
7467                 r_waterstate.texturewidth = texturewidth;
7468                 r_waterstate.textureheight = textureheight;
7469                 r_waterstate.camerawidth = camerawidth;
7470                 r_waterstate.cameraheight = cameraheight;
7471         }
7472
7473         if (r_waterstate.texturewidth)
7474         {
7475                 r_waterstate.enabled = true;
7476
7477                 // when doing a reduced render (HDR) we want to use a smaller area
7478                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
7479                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
7480
7481                 // set up variables that will be used in shader setup
7482                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7483                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7484                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7485                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7486         }
7487
7488         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7489         r_waterstate.numwaterplanes = 0;
7490 }
7491
7492 void R_Water_AddWaterPlane(msurface_t *surface)
7493 {
7494         int triangleindex, planeindex;
7495         const int *e;
7496         vec3_t vert[3];
7497         vec3_t normal;
7498         vec3_t center;
7499         mplane_t plane;
7500         int cam_ent;
7501         r_waterstate_waterplane_t *p;
7502         texture_t *t = R_GetCurrentTexture(surface->texture);
7503         cam_ent = t->camera_entity;
7504         if(!(t->currentmaterialflags & MATERIALFLAG_CAMERA))
7505                 cam_ent = 0;
7506
7507         // just use the first triangle with a valid normal for any decisions
7508         VectorClear(normal);
7509         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
7510         {
7511                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
7512                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
7513                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
7514                 TriangleNormal(vert[0], vert[1], vert[2], normal);
7515                 if (VectorLength2(normal) >= 0.001)
7516                         break;
7517         }
7518
7519         VectorCopy(normal, plane.normal);
7520         VectorNormalize(plane.normal);
7521         plane.dist = DotProduct(vert[0], plane.normal);
7522         PlaneClassify(&plane);
7523         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
7524         {
7525                 // skip backfaces (except if nocullface is set)
7526                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
7527                         return;
7528                 VectorNegate(plane.normal, plane.normal);
7529                 plane.dist *= -1;
7530                 PlaneClassify(&plane);
7531         }
7532
7533
7534         // find a matching plane if there is one
7535         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7536                 if(p->camera_entity == t->camera_entity)
7537                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
7538                                 break;
7539         if (planeindex >= r_waterstate.maxwaterplanes)
7540                 return; // nothing we can do, out of planes
7541
7542         // if this triangle does not fit any known plane rendered this frame, add one
7543         if (planeindex >= r_waterstate.numwaterplanes)
7544         {
7545                 // store the new plane
7546                 r_waterstate.numwaterplanes++;
7547                 p->plane = plane;
7548                 // clear materialflags and pvs
7549                 p->materialflags = 0;
7550                 p->pvsvalid = false;
7551                 p->camera_entity = t->camera_entity;
7552         }
7553         // merge this surface's materialflags into the waterplane
7554         p->materialflags |= t->currentmaterialflags;
7555         if(!(p->materialflags & MATERIALFLAG_CAMERA))
7556         {
7557                 // merge this surface's PVS into the waterplane
7558                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
7559                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
7560                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
7561                 {
7562                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
7563                         p->pvsvalid = true;
7564                 }
7565         }
7566 }
7567
7568 static void R_Water_ProcessPlanes(void)
7569 {
7570         r_refdef_view_t originalview;
7571         r_refdef_view_t myview;
7572         int planeindex;
7573         r_waterstate_waterplane_t *p;
7574         vec3_t visorigin;
7575
7576         originalview = r_refdef.view;
7577
7578         // make sure enough textures are allocated
7579         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7580         {
7581                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7582                 {
7583                         if (!p->texture_refraction)
7584                                 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);
7585                         if (!p->texture_refraction)
7586                                 goto error;
7587                 }
7588                 else if (p->materialflags & MATERIALFLAG_CAMERA)
7589                 {
7590                         if (!p->texture_camera)
7591                                 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);
7592                         if (!p->texture_camera)
7593                                 goto error;
7594                 }
7595
7596                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7597                 {
7598                         if (!p->texture_reflection)
7599                                 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);
7600                         if (!p->texture_reflection)
7601                                 goto error;
7602                 }
7603         }
7604
7605         // render views
7606         r_refdef.view = originalview;
7607         r_refdef.view.showdebug = false;
7608         r_refdef.view.width = r_waterstate.waterwidth;
7609         r_refdef.view.height = r_waterstate.waterheight;
7610         r_refdef.view.useclipplane = true;
7611         myview = r_refdef.view;
7612         r_waterstate.renderingscene = true;
7613         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7614         {
7615                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7616                 {
7617                         r_refdef.view = myview;
7618                         // render reflected scene and copy into texture
7619                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
7620                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
7621                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
7622                         r_refdef.view.clipplane = p->plane;
7623                         // reverse the cullface settings for this render
7624                         r_refdef.view.cullface_front = GL_FRONT;
7625                         r_refdef.view.cullface_back = GL_BACK;
7626                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
7627                         {
7628                                 r_refdef.view.usecustompvs = true;
7629                                 if (p->pvsvalid)
7630                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7631                                 else
7632                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7633                         }
7634
7635                         R_ResetViewRendering3D();
7636                         R_ClearScreen(r_refdef.fogenabled);
7637                         R_View_Update();
7638                         R_RenderScene();
7639
7640                         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);
7641                 }
7642
7643                 // render the normal view scene and copy into texture
7644                 // (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)
7645                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7646                 {
7647                         r_waterstate.renderingrefraction = true;
7648                         r_refdef.view = myview;
7649
7650                         r_refdef.view.clipplane = p->plane;
7651                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
7652                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
7653
7654                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
7655                         {
7656                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
7657                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
7658                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
7659                                 R_RenderView_UpdateViewVectors();
7660                                 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);
7661                         }
7662
7663                         PlaneClassify(&r_refdef.view.clipplane);
7664
7665                         R_ResetViewRendering3D();
7666                         R_ClearScreen(r_refdef.fogenabled);
7667                         R_View_Update();
7668                         R_RenderScene();
7669
7670                         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);
7671                         r_waterstate.renderingrefraction = false;
7672                 }
7673                 else if (p->materialflags & MATERIALFLAG_CAMERA)
7674                 {
7675                         r_refdef.view = myview;
7676
7677                         r_refdef.view.clipplane = p->plane;
7678                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
7679                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
7680
7681                         r_refdef.view.width = r_waterstate.camerawidth;
7682                         r_refdef.view.height = r_waterstate.cameraheight;
7683                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
7684                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
7685
7686                         if(p->camera_entity)
7687                         {
7688                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
7689                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
7690                         }
7691
7692                         // reverse the cullface settings for this render
7693                         r_refdef.view.cullface_front = GL_FRONT;
7694                         r_refdef.view.cullface_back = GL_BACK;
7695                         // also reverse the view matrix
7696                         Matrix4x4_ConcatScale3(&r_refdef.view.matrix, 1, -1, 1);
7697                         R_RenderView_UpdateViewVectors();
7698                         if(p->camera_entity)
7699                                 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);
7700                         
7701                         // camera needs no clipplane
7702                         r_refdef.view.useclipplane = false;
7703
7704                         PlaneClassify(&r_refdef.view.clipplane);
7705
7706                         R_ResetViewRendering3D();
7707                         R_ClearScreen(r_refdef.fogenabled);
7708                         R_View_Update();
7709                         R_RenderScene();
7710
7711                         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);
7712                         r_waterstate.renderingrefraction = false;
7713                 }
7714
7715         }
7716         r_waterstate.renderingscene = false;
7717         r_refdef.view = originalview;
7718         R_ResetViewRendering3D();
7719         R_ClearScreen(r_refdef.fogenabled);
7720         R_View_Update();
7721         return;
7722 error:
7723         r_refdef.view = originalview;
7724         r_waterstate.renderingscene = false;
7725         Cvar_SetValueQuick(&r_water, 0);
7726         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
7727         return;
7728 }
7729
7730 void R_Bloom_StartFrame(void)
7731 {
7732         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
7733
7734         switch(vid.renderpath)
7735         {
7736         case RENDERPATH_GL20:
7737         case RENDERPATH_CGGL:
7738                 break;
7739         case RENDERPATH_GL13:
7740         case RENDERPATH_GL11:
7741                 return;
7742         }
7743
7744         // set bloomwidth and bloomheight to the bloom resolution that will be
7745         // used (often less than the screen resolution for faster rendering)
7746         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
7747         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
7748         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
7749         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
7750         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
7751
7752         // calculate desired texture sizes
7753         if (vid.support.arb_texture_non_power_of_two)
7754         {
7755                 screentexturewidth = r_refdef.view.width;
7756                 screentextureheight = r_refdef.view.height;
7757                 bloomtexturewidth = r_bloomstate.bloomwidth;
7758                 bloomtextureheight = r_bloomstate.bloomheight;
7759         }
7760         else
7761         {
7762                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
7763                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
7764                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
7765                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
7766         }
7767
7768         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))
7769         {
7770                 Cvar_SetValueQuick(&r_hdr, 0);
7771                 Cvar_SetValueQuick(&r_bloom, 0);
7772                 Cvar_SetValueQuick(&r_motionblur, 0);
7773                 Cvar_SetValueQuick(&r_damageblur, 0);
7774         }
7775
7776         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)))
7777                 screentexturewidth = screentextureheight = 0;
7778         if (!r_hdr.integer && !r_bloom.integer)
7779                 bloomtexturewidth = bloomtextureheight = 0;
7780
7781         // allocate textures as needed
7782         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
7783         {
7784                 if (r_bloomstate.texture_screen)
7785                         R_FreeTexture(r_bloomstate.texture_screen);
7786                 r_bloomstate.texture_screen = NULL;
7787                 r_bloomstate.screentexturewidth = screentexturewidth;
7788                 r_bloomstate.screentextureheight = screentextureheight;
7789                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
7790                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
7791         }
7792         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
7793         {
7794                 if (r_bloomstate.texture_bloom)
7795                         R_FreeTexture(r_bloomstate.texture_bloom);
7796                 r_bloomstate.texture_bloom = NULL;
7797                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
7798                 r_bloomstate.bloomtextureheight = bloomtextureheight;
7799                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
7800                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7801         }
7802
7803         // when doing a reduced render (HDR) we want to use a smaller area
7804         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
7805         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
7806         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
7807         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
7808         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
7809
7810         // set up a texcoord array for the full resolution screen image
7811         // (we have to keep this around to copy back during final render)
7812         r_bloomstate.screentexcoord2f[0] = 0;
7813         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7814         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7815         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7816         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7817         r_bloomstate.screentexcoord2f[5] = 0;
7818         r_bloomstate.screentexcoord2f[6] = 0;
7819         r_bloomstate.screentexcoord2f[7] = 0;
7820
7821         // set up a texcoord array for the reduced resolution bloom image
7822         // (which will be additive blended over the screen image)
7823         r_bloomstate.bloomtexcoord2f[0] = 0;
7824         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7825         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7826         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7827         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7828         r_bloomstate.bloomtexcoord2f[5] = 0;
7829         r_bloomstate.bloomtexcoord2f[6] = 0;
7830         r_bloomstate.bloomtexcoord2f[7] = 0;
7831
7832         if (r_hdr.integer || r_bloom.integer)
7833         {
7834                 r_bloomstate.enabled = true;
7835                 r_bloomstate.hdr = r_hdr.integer != 0;
7836         }
7837
7838         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);
7839 }
7840
7841 void R_Bloom_CopyBloomTexture(float colorscale)
7842 {
7843         r_refdef.stats.bloom++;
7844
7845         // scale down screen texture to the bloom texture size
7846         CHECKGLERROR
7847         R_SetViewport(&r_bloomstate.viewport);
7848         GL_BlendFunc(GL_ONE, GL_ZERO);
7849         GL_Color(colorscale, colorscale, colorscale, 1);
7850         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
7851         // TODO: do boxfilter scale-down in shader?
7852         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7853         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
7854         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7855
7856         // we now have a bloom image in the framebuffer
7857         // copy it into the bloom image texture for later processing
7858         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);
7859         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7860 }
7861
7862 void R_Bloom_CopyHDRTexture(void)
7863 {
7864         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);
7865         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7866 }
7867
7868 void R_Bloom_MakeTexture(void)
7869 {
7870         int x, range, dir;
7871         float xoffset, yoffset, r, brighten;
7872
7873         r_refdef.stats.bloom++;
7874
7875         R_ResetViewRendering2D();
7876
7877         // we have a bloom image in the framebuffer
7878         CHECKGLERROR
7879         R_SetViewport(&r_bloomstate.viewport);
7880
7881         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
7882         {
7883                 x *= 2;
7884                 r = bound(0, r_bloom_colorexponent.value / x, 1);
7885                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7886                 GL_Color(r,r,r,1);
7887                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
7888                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7889                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
7890                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7891
7892                 // copy the vertically blurred bloom view to a texture
7893                 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
7894                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7895         }
7896
7897         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
7898         brighten = r_bloom_brighten.value;
7899         if (r_hdr.integer)
7900                 brighten *= r_hdr_range.value;
7901         brighten = sqrt(brighten);
7902         if(range >= 1)
7903                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
7904         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7905
7906         for (dir = 0;dir < 2;dir++)
7907         {
7908                 // blend on at multiple vertical offsets to achieve a vertical blur
7909                 // TODO: do offset blends using GLSL
7910                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
7911                 GL_BlendFunc(GL_ONE, GL_ZERO);
7912                 for (x = -range;x <= range;x++)
7913                 {
7914                         if (!dir){xoffset = 0;yoffset = x;}
7915                         else {xoffset = x;yoffset = 0;}
7916                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
7917                         yoffset /= (float)r_bloomstate.bloomtextureheight;
7918                         // compute a texcoord array with the specified x and y offset
7919                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
7920                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7921                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7922                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7923                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7924                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
7925                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
7926                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
7927                         // this r value looks like a 'dot' particle, fading sharply to
7928                         // black at the edges
7929                         // (probably not realistic but looks good enough)
7930                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
7931                         //r = brighten/(range*2+1);
7932                         r = brighten / (range * 2 + 1);
7933                         if(range >= 1)
7934                                 r *= (1 - x*x/(float)(range*range));
7935                         GL_Color(r, r, r, 1);
7936                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
7937                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
7938                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7939                         GL_BlendFunc(GL_ONE, GL_ONE);
7940                 }
7941
7942                 // copy the vertically blurred bloom view to a texture
7943                 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);
7944                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7945         }
7946
7947         // apply subtract last
7948         // (just like it would be in a GLSL shader)
7949         if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
7950         {
7951                 GL_BlendFunc(GL_ONE, GL_ZERO);
7952                 GL_Color(1,1,1,1);
7953                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
7954                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7955                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
7956                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7957
7958                 GL_BlendFunc(GL_ONE, GL_ONE);
7959                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
7960                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7961                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
7962                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
7963                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
7964                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7965                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
7966
7967                 // copy the darkened bloom view to a texture
7968                 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);
7969                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7970         }
7971 }
7972
7973 void R_HDR_RenderBloomTexture(void)
7974 {
7975         int oldwidth, oldheight;
7976         float oldcolorscale;
7977
7978         oldcolorscale = r_refdef.view.colorscale;
7979         oldwidth = r_refdef.view.width;
7980         oldheight = r_refdef.view.height;
7981         r_refdef.view.width = r_bloomstate.bloomwidth;
7982         r_refdef.view.height = r_bloomstate.bloomheight;
7983
7984         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
7985         // TODO: add exposure compensation features
7986         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
7987
7988         r_refdef.view.showdebug = false;
7989         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
7990
7991         R_ResetViewRendering3D();
7992
7993         R_ClearScreen(r_refdef.fogenabled);
7994         if (r_timereport_active)
7995                 R_TimeReport("HDRclear");
7996
7997         R_View_Update();
7998         if (r_timereport_active)
7999                 R_TimeReport("visibility");
8000
8001         // only do secondary renders with HDR if r_hdr is 2 or higher
8002         r_waterstate.numwaterplanes = 0;
8003         if (r_waterstate.enabled && r_hdr.integer >= 2)
8004                 R_RenderWaterPlanes();
8005
8006         r_refdef.view.showdebug = true;
8007         R_RenderScene();
8008         r_waterstate.numwaterplanes = 0;
8009
8010         R_ResetViewRendering2D();
8011
8012         R_Bloom_CopyHDRTexture();
8013         R_Bloom_MakeTexture();
8014
8015         // restore the view settings
8016         r_refdef.view.width = oldwidth;
8017         r_refdef.view.height = oldheight;
8018         r_refdef.view.colorscale = oldcolorscale;
8019
8020         R_ResetViewRendering3D();
8021
8022         R_ClearScreen(r_refdef.fogenabled);
8023         if (r_timereport_active)
8024                 R_TimeReport("viewclear");
8025 }
8026
8027 static void R_BlendView(void)
8028 {
8029         unsigned int permutation;
8030         float uservecs[4][4];
8031
8032         switch (vid.renderpath)
8033         {
8034         case RENDERPATH_GL20:
8035         case RENDERPATH_CGGL:
8036                 permutation =
8037                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
8038                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
8039                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
8040                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
8041                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
8042
8043                 if (r_bloomstate.texture_screen)
8044                 {
8045                         // make sure the buffer is available
8046                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
8047
8048                         R_ResetViewRendering2D();
8049
8050                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
8051                         {
8052                                 // declare variables
8053                                 float speed;
8054                                 static float avgspeed;
8055
8056                                 speed = VectorLength(cl.movement_velocity);
8057
8058                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
8059                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
8060
8061                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
8062                                 speed = bound(0, speed, 1);
8063                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
8064
8065                                 // calculate values into a standard alpha
8066                                 cl.motionbluralpha = 1 - exp(-
8067                                                 (
8068                                                  (r_motionblur.value * speed / 80)
8069                                                  +
8070                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
8071                                                 )
8072                                                 /
8073                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
8074                                            );
8075
8076                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
8077                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
8078                                 // apply the blur
8079                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
8080                                 {
8081                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8082                                         GL_Color(1, 1, 1, cl.motionbluralpha);
8083                                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8084                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8085                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8086                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8087                                 }
8088                         }
8089
8090                         // copy view into the screen texture
8091                         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);
8092                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8093                 }
8094                 else if (!r_bloomstate.texture_bloom)
8095                 {
8096                         // we may still have to do view tint...
8097                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8098                         {
8099                                 // apply a color tint to the whole view
8100                                 R_ResetViewRendering2D();
8101                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8102                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
8103                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8104                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8105                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8106                         }
8107                         break; // no screen processing, no bloom, skip it
8108                 }
8109
8110                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
8111                 {
8112                         // render simple bloom effect
8113                         // copy the screen and shrink it and darken it for the bloom process
8114                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
8115                         // make the bloom texture
8116                         R_Bloom_MakeTexture();
8117                 }
8118
8119 #if _MSC_VER >= 1400
8120 #define sscanf sscanf_s
8121 #endif
8122                 memset(uservecs, 0, sizeof(uservecs));
8123                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
8124                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
8125                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
8126                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
8127
8128                 R_ResetViewRendering2D();
8129                 GL_Color(1, 1, 1, 1);
8130                 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8131                 GL_BlendFunc(GL_ONE, GL_ZERO);
8132
8133                 switch(vid.renderpath)
8134                 {
8135                 case RENDERPATH_GL20:
8136                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
8137                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
8138                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
8139                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
8140                         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]);
8141                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8142                         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]);
8143                         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]);
8144                         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]);
8145                         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]);
8146                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
8147                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
8148                         break;
8149                 case RENDERPATH_CGGL:
8150 #ifdef SUPPORTCG
8151                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
8152                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
8153                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
8154                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
8155                         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
8156                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
8157                         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
8158                         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
8159                         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
8160                         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
8161                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
8162                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
8163 #endif
8164                         break;
8165                 default:
8166                         break;
8167                 }
8168                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8169                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8170                 break;
8171         case RENDERPATH_GL13:
8172         case RENDERPATH_GL11:
8173                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8174                 {
8175                         // apply a color tint to the whole view
8176                         R_ResetViewRendering2D();
8177                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8178                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
8179                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8180                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8181                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8182                 }
8183                 break;
8184         }
8185 }
8186
8187 matrix4x4_t r_waterscrollmatrix;
8188
8189 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
8190 {
8191         if (r_refdef.fog_density)
8192         {
8193                 r_refdef.fogcolor[0] = r_refdef.fog_red;
8194                 r_refdef.fogcolor[1] = r_refdef.fog_green;
8195                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
8196
8197                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
8198                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
8199                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
8200                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
8201
8202                 {
8203                         vec3_t fogvec;
8204                         VectorCopy(r_refdef.fogcolor, fogvec);
8205                         //   color.rgb *= ContrastBoost * SceneBrightness;
8206                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
8207                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
8208                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
8209                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
8210                 }
8211         }
8212 }
8213
8214 void R_UpdateVariables(void)
8215 {
8216         R_Textures_Frame();
8217
8218         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
8219
8220         r_refdef.farclip = r_farclip_base.value;
8221         if (r_refdef.scene.worldmodel)
8222                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
8223         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
8224
8225         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
8226                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
8227         r_refdef.polygonfactor = 0;
8228         r_refdef.polygonoffset = 0;
8229         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8230         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8231
8232         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
8233         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
8234         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
8235         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
8236         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
8237         if (r_showsurfaces.integer)
8238         {
8239                 r_refdef.scene.rtworld = false;
8240                 r_refdef.scene.rtworldshadows = false;
8241                 r_refdef.scene.rtdlight = false;
8242                 r_refdef.scene.rtdlightshadows = false;
8243                 r_refdef.lightmapintensity = 0;
8244         }
8245
8246         if (gamemode == GAME_NEHAHRA)
8247         {
8248                 if (gl_fogenable.integer)
8249                 {
8250                         r_refdef.oldgl_fogenable = true;
8251                         r_refdef.fog_density = gl_fogdensity.value;
8252                         r_refdef.fog_red = gl_fogred.value;
8253                         r_refdef.fog_green = gl_foggreen.value;
8254                         r_refdef.fog_blue = gl_fogblue.value;
8255                         r_refdef.fog_alpha = 1;
8256                         r_refdef.fog_start = 0;
8257                         r_refdef.fog_end = gl_skyclip.value;
8258                         r_refdef.fog_height = 1<<30;
8259                         r_refdef.fog_fadedepth = 128;
8260                 }
8261                 else if (r_refdef.oldgl_fogenable)
8262                 {
8263                         r_refdef.oldgl_fogenable = false;
8264                         r_refdef.fog_density = 0;
8265                         r_refdef.fog_red = 0;
8266                         r_refdef.fog_green = 0;
8267                         r_refdef.fog_blue = 0;
8268                         r_refdef.fog_alpha = 0;
8269                         r_refdef.fog_start = 0;
8270                         r_refdef.fog_end = 0;
8271                         r_refdef.fog_height = 1<<30;
8272                         r_refdef.fog_fadedepth = 128;
8273                 }
8274         }
8275
8276         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
8277         r_refdef.fog_start = max(0, r_refdef.fog_start);
8278         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
8279
8280         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
8281
8282         if (r_refdef.fog_density && r_drawfog.integer)
8283         {
8284                 r_refdef.fogenabled = true;
8285                 // this is the point where the fog reaches 0.9986 alpha, which we
8286                 // consider a good enough cutoff point for the texture
8287                 // (0.9986 * 256 == 255.6)
8288                 if (r_fog_exp2.integer)
8289                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
8290                 else
8291                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
8292                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
8293                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
8294                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
8295                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
8296                         R_BuildFogHeightTexture();
8297                 // fog color was already set
8298                 // update the fog texture
8299                 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)
8300                         R_BuildFogTexture();
8301                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
8302                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
8303         }
8304         else
8305                 r_refdef.fogenabled = false;
8306
8307         switch(vid.renderpath)
8308         {
8309         case RENDERPATH_GL20:
8310         case RENDERPATH_CGGL:
8311                 if(v_glslgamma.integer && !vid_gammatables_trivial)
8312                 {
8313                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
8314                         {
8315                                 // build GLSL gamma texture
8316 #define RAMPWIDTH 256
8317                                 unsigned short ramp[RAMPWIDTH * 3];
8318                                 unsigned char rampbgr[RAMPWIDTH][4];
8319                                 int i;
8320
8321                                 r_texture_gammaramps_serial = vid_gammatables_serial;
8322
8323                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
8324                                 for(i = 0; i < RAMPWIDTH; ++i)
8325                                 {
8326                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8327                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8328                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
8329                                         rampbgr[i][3] = 0;
8330                                 }
8331                                 if (r_texture_gammaramps)
8332                                 {
8333                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
8334                                 }
8335                                 else
8336                                 {
8337                                         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);
8338                                 }
8339                         }
8340                 }
8341                 else
8342                 {
8343                         // remove GLSL gamma texture
8344                 }
8345                 break;
8346         case RENDERPATH_GL13:
8347         case RENDERPATH_GL11:
8348                 break;
8349         }
8350 }
8351
8352 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
8353 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
8354 /*
8355 ================
8356 R_SelectScene
8357 ================
8358 */
8359 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
8360         if( scenetype != r_currentscenetype ) {
8361                 // store the old scenetype
8362                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
8363                 r_currentscenetype = scenetype;
8364                 // move in the new scene
8365                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
8366         }
8367 }
8368
8369 /*
8370 ================
8371 R_GetScenePointer
8372 ================
8373 */
8374 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
8375 {
8376         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
8377         if( scenetype == r_currentscenetype ) {
8378                 return &r_refdef.scene;
8379         } else {
8380                 return &r_scenes_store[ scenetype ];
8381         }
8382 }
8383
8384 /*
8385 ================
8386 R_RenderView
8387 ================
8388 */
8389 void R_RenderView(void)
8390 {
8391         if (r_timereport_active)
8392                 R_TimeReport("start");
8393         r_textureframe++; // used only by R_GetCurrentTexture
8394         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8395
8396         if (!r_drawentities.integer)
8397                 r_refdef.scene.numentities = 0;
8398
8399         R_AnimCache_ClearCache();
8400         R_FrameData_NewFrame();
8401
8402         if (r_refdef.view.isoverlay)
8403         {
8404                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
8405                 GL_Clear( GL_DEPTH_BUFFER_BIT );
8406                 R_TimeReport("depthclear");
8407
8408                 r_refdef.view.showdebug = false;
8409
8410                 r_waterstate.enabled = false;
8411                 r_waterstate.numwaterplanes = 0;
8412
8413                 R_RenderScene();
8414
8415                 CHECKGLERROR
8416                 return;
8417         }
8418
8419         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
8420                 return; //Host_Error ("R_RenderView: NULL worldmodel");
8421
8422         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
8423
8424         R_RenderView_UpdateViewVectors();
8425
8426         R_Shadow_UpdateWorldLightSelection();
8427
8428         R_Bloom_StartFrame();
8429         R_Water_StartFrame();
8430
8431         CHECKGLERROR
8432         if (r_timereport_active)
8433                 R_TimeReport("viewsetup");
8434
8435         R_ResetViewRendering3D();
8436
8437         if (r_refdef.view.clear || r_refdef.fogenabled)
8438         {
8439                 R_ClearScreen(r_refdef.fogenabled);
8440                 if (r_timereport_active)
8441                         R_TimeReport("viewclear");
8442         }
8443         r_refdef.view.clear = true;
8444
8445         // this produces a bloom texture to be used in R_BlendView() later
8446         if (r_hdr.integer && r_bloomstate.bloomwidth)
8447         {
8448                 R_HDR_RenderBloomTexture();
8449                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
8450                 r_textureframe++; // used only by R_GetCurrentTexture
8451         }
8452
8453         r_refdef.view.showdebug = true;
8454
8455         R_View_Update();
8456         if (r_timereport_active)
8457                 R_TimeReport("visibility");
8458
8459         r_waterstate.numwaterplanes = 0;
8460         if (r_waterstate.enabled)
8461                 R_RenderWaterPlanes();
8462
8463         R_RenderScene();
8464         r_waterstate.numwaterplanes = 0;
8465
8466         R_BlendView();
8467         if (r_timereport_active)
8468                 R_TimeReport("blendview");
8469
8470         GL_Scissor(0, 0, vid.width, vid.height);
8471         GL_ScissorTest(false);
8472         CHECKGLERROR
8473 }
8474
8475 void R_RenderWaterPlanes(void)
8476 {
8477         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
8478         {
8479                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
8480                 if (r_timereport_active)
8481                         R_TimeReport("waterworld");
8482         }
8483
8484         // don't let sound skip if going slow
8485         if (r_refdef.scene.extraupdate)
8486                 S_ExtraUpdate ();
8487
8488         R_DrawModelsAddWaterPlanes();
8489         if (r_timereport_active)
8490                 R_TimeReport("watermodels");
8491
8492         if (r_waterstate.numwaterplanes)
8493         {
8494                 R_Water_ProcessPlanes();
8495                 if (r_timereport_active)
8496                         R_TimeReport("waterscenes");
8497         }
8498 }
8499
8500 extern void R_DrawLightningBeams (void);
8501 extern void VM_CL_AddPolygonsToMeshQueue (void);
8502 extern void R_DrawPortals (void);
8503 extern cvar_t cl_locs_show;
8504 static void R_DrawLocs(void);
8505 static void R_DrawEntityBBoxes(void);
8506 static void R_DrawModelDecals(void);
8507 extern void R_DrawModelShadows(void);
8508 extern void R_DrawModelShadowMaps(void);
8509 extern cvar_t cl_decals_newsystem;
8510 extern qboolean r_shadow_usingdeferredprepass;
8511 void R_RenderScene(void)
8512 {
8513         qboolean shadowmapping = false;
8514
8515         if (r_timereport_active)
8516                 R_TimeReport("beginscene");
8517
8518         r_refdef.stats.renders++;
8519
8520         R_UpdateFogColor();
8521
8522         // don't let sound skip if going slow
8523         if (r_refdef.scene.extraupdate)
8524                 S_ExtraUpdate ();
8525
8526         R_MeshQueue_BeginScene();
8527
8528         R_SkyStartFrame();
8529
8530         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);
8531
8532         if (r_timereport_active)
8533                 R_TimeReport("skystartframe");
8534
8535         if (cl.csqc_vidvars.drawworld)
8536         {
8537                 // don't let sound skip if going slow
8538                 if (r_refdef.scene.extraupdate)
8539                         S_ExtraUpdate ();
8540
8541                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
8542                 {
8543                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
8544                         if (r_timereport_active)
8545                                 R_TimeReport("worldsky");
8546                 }
8547
8548                 if (R_DrawBrushModelsSky() && r_timereport_active)
8549                         R_TimeReport("bmodelsky");
8550
8551                 if (skyrendermasked && skyrenderlater)
8552                 {
8553                         // we have to force off the water clipping plane while rendering sky
8554                         R_SetupView(false);
8555                         R_Sky();
8556                         R_SetupView(true);
8557                         if (r_timereport_active)
8558                                 R_TimeReport("sky");
8559                 }
8560         }
8561
8562         R_AnimCache_CacheVisibleEntities();
8563         if (r_timereport_active)
8564                 R_TimeReport("animation");
8565
8566         R_Shadow_PrepareLights();
8567         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
8568                 R_Shadow_PrepareModelShadows();
8569         if (r_timereport_active)
8570                 R_TimeReport("preparelights");
8571
8572         if (R_Shadow_ShadowMappingEnabled())
8573                 shadowmapping = true;
8574
8575         if (r_shadow_usingdeferredprepass)
8576                 R_Shadow_DrawPrepass();
8577
8578         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
8579         {
8580                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
8581                 if (r_timereport_active)
8582                         R_TimeReport("worlddepth");
8583         }
8584         if (r_depthfirst.integer >= 2)
8585         {
8586                 R_DrawModelsDepth();
8587                 if (r_timereport_active)
8588                         R_TimeReport("modeldepth");
8589         }
8590
8591         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
8592         {
8593                 R_DrawModelShadowMaps();
8594                 R_ResetViewRendering3D();
8595                 // don't let sound skip if going slow
8596                 if (r_refdef.scene.extraupdate)
8597                         S_ExtraUpdate ();
8598         }
8599
8600         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
8601         {
8602                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
8603                 if (r_timereport_active)
8604                         R_TimeReport("world");
8605         }
8606
8607         // don't let sound skip if going slow
8608         if (r_refdef.scene.extraupdate)
8609                 S_ExtraUpdate ();
8610
8611         R_DrawModels();
8612         if (r_timereport_active)
8613                 R_TimeReport("models");
8614
8615         // don't let sound skip if going slow
8616         if (r_refdef.scene.extraupdate)
8617                 S_ExtraUpdate ();
8618
8619         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8620         {
8621                 R_DrawModelShadows();
8622                 R_ResetViewRendering3D();
8623                 // don't let sound skip if going slow
8624                 if (r_refdef.scene.extraupdate)
8625                         S_ExtraUpdate ();
8626         }
8627
8628         if (!r_shadow_usingdeferredprepass)
8629         {
8630                 R_Shadow_DrawLights();
8631                 if (r_timereport_active)
8632                         R_TimeReport("rtlights");
8633         }
8634
8635         // don't let sound skip if going slow
8636         if (r_refdef.scene.extraupdate)
8637                 S_ExtraUpdate ();
8638
8639         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8640         {
8641                 R_DrawModelShadows();
8642                 R_ResetViewRendering3D();
8643                 // don't let sound skip if going slow
8644                 if (r_refdef.scene.extraupdate)
8645                         S_ExtraUpdate ();
8646         }
8647
8648         if (cl.csqc_vidvars.drawworld)
8649         {
8650                 if (cl_decals_newsystem.integer)
8651                 {
8652                         R_DrawModelDecals();
8653                         if (r_timereport_active)
8654                                 R_TimeReport("modeldecals");
8655                 }
8656                 else
8657                 {
8658                         R_DrawDecals();
8659                         if (r_timereport_active)
8660                                 R_TimeReport("decals");
8661                 }
8662
8663                 R_DrawParticles();
8664                 if (r_timereport_active)
8665                         R_TimeReport("particles");
8666
8667                 R_DrawExplosions();
8668                 if (r_timereport_active)
8669                         R_TimeReport("explosions");
8670
8671                 R_DrawLightningBeams();
8672                 if (r_timereport_active)
8673                         R_TimeReport("lightning");
8674         }
8675
8676         VM_CL_AddPolygonsToMeshQueue();
8677
8678         if (r_refdef.view.showdebug)
8679         {
8680                 if (cl_locs_show.integer)
8681                 {
8682                         R_DrawLocs();
8683                         if (r_timereport_active)
8684                                 R_TimeReport("showlocs");
8685                 }
8686
8687                 if (r_drawportals.integer)
8688                 {
8689                         R_DrawPortals();
8690                         if (r_timereport_active)
8691                                 R_TimeReport("portals");
8692                 }
8693
8694                 if (r_showbboxes.value > 0)
8695                 {
8696                         R_DrawEntityBBoxes();
8697                         if (r_timereport_active)
8698                                 R_TimeReport("bboxes");
8699                 }
8700         }
8701
8702         R_MeshQueue_RenderTransparent();
8703         if (r_timereport_active)
8704                 R_TimeReport("drawtrans");
8705
8706         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))
8707         {
8708                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
8709                 if (r_timereport_active)
8710                         R_TimeReport("worlddebug");
8711                 R_DrawModelsDebug();
8712                 if (r_timereport_active)
8713                         R_TimeReport("modeldebug");
8714         }
8715
8716         if (cl.csqc_vidvars.drawworld)
8717         {
8718                 R_Shadow_DrawCoronas();
8719                 if (r_timereport_active)
8720                         R_TimeReport("coronas");
8721         }
8722
8723         // don't let sound skip if going slow
8724         if (r_refdef.scene.extraupdate)
8725                 S_ExtraUpdate ();
8726
8727         R_ResetViewRendering2D();
8728 }
8729
8730 static const unsigned short bboxelements[36] =
8731 {
8732         5, 1, 3, 5, 3, 7,
8733         6, 2, 0, 6, 0, 4,
8734         7, 3, 2, 7, 2, 6,
8735         4, 0, 1, 4, 1, 5,
8736         4, 5, 7, 4, 7, 6,
8737         1, 0, 2, 1, 2, 3,
8738 };
8739
8740 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
8741 {
8742         int i;
8743         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
8744
8745         RSurf_ActiveWorldEntity();
8746
8747         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8748         GL_DepthMask(false);
8749         GL_DepthRange(0, 1);
8750         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8751         R_Mesh_ResetTextureState();
8752
8753         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
8754         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
8755         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
8756         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
8757         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
8758         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
8759         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
8760         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
8761         R_FillColors(color4f, 8, cr, cg, cb, ca);
8762         if (r_refdef.fogenabled)
8763         {
8764                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
8765                 {
8766                         f1 = RSurf_FogVertex(v);
8767                         f2 = 1 - f1;
8768                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
8769                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
8770                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
8771                 }
8772         }
8773         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
8774         R_Mesh_ResetTextureState();
8775         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8776         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
8777 }
8778
8779 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8780 {
8781         int i;
8782         float color[4];
8783         prvm_edict_t *edict;
8784         prvm_prog_t *prog_save = prog;
8785
8786         // this function draws bounding boxes of server entities
8787         if (!sv.active)
8788                 return;
8789
8790         GL_CullFace(GL_NONE);
8791         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8792
8793         prog = 0;
8794         SV_VM_Begin();
8795         for (i = 0;i < numsurfaces;i++)
8796         {
8797                 edict = PRVM_EDICT_NUM(surfacelist[i]);
8798                 switch ((int)edict->fields.server->solid)
8799                 {
8800                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
8801                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
8802                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
8803                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
8804                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
8805                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
8806                 }
8807                 color[3] *= r_showbboxes.value;
8808                 color[3] = bound(0, color[3], 1);
8809                 GL_DepthTest(!r_showdisabledepthtest.integer);
8810                 GL_CullFace(r_refdef.view.cullface_front);
8811                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
8812         }
8813         SV_VM_End();
8814         prog = prog_save;
8815 }
8816
8817 static void R_DrawEntityBBoxes(void)
8818 {
8819         int i;
8820         prvm_edict_t *edict;
8821         vec3_t center;
8822         prvm_prog_t *prog_save = prog;
8823
8824         // this function draws bounding boxes of server entities
8825         if (!sv.active)
8826                 return;
8827
8828         prog = 0;
8829         SV_VM_Begin();
8830         for (i = 0;i < prog->num_edicts;i++)
8831         {
8832                 edict = PRVM_EDICT_NUM(i);
8833                 if (edict->priv.server->free)
8834                         continue;
8835                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
8836                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
8837                         continue;
8838                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
8839                         continue;
8840                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
8841                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
8842         }
8843         SV_VM_End();
8844         prog = prog_save;
8845 }
8846
8847 static const int nomodelelement3i[24] =
8848 {
8849         5, 2, 0,
8850         5, 1, 2,
8851         5, 0, 3,
8852         5, 3, 1,
8853         0, 2, 4,
8854         2, 1, 4,
8855         3, 0, 4,
8856         1, 3, 4
8857 };
8858
8859 static const unsigned short nomodelelement3s[24] =
8860 {
8861         5, 2, 0,
8862         5, 1, 2,
8863         5, 0, 3,
8864         5, 3, 1,
8865         0, 2, 4,
8866         2, 1, 4,
8867         3, 0, 4,
8868         1, 3, 4
8869 };
8870
8871 static const float nomodelvertex3f[6*3] =
8872 {
8873         -16,   0,   0,
8874          16,   0,   0,
8875           0, -16,   0,
8876           0,  16,   0,
8877           0,   0, -16,
8878           0,   0,  16
8879 };
8880
8881 static const float nomodelcolor4f[6*4] =
8882 {
8883         0.0f, 0.0f, 0.5f, 1.0f,
8884         0.0f, 0.0f, 0.5f, 1.0f,
8885         0.0f, 0.5f, 0.0f, 1.0f,
8886         0.0f, 0.5f, 0.0f, 1.0f,
8887         0.5f, 0.0f, 0.0f, 1.0f,
8888         0.5f, 0.0f, 0.0f, 1.0f
8889 };
8890
8891 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8892 {
8893         int i;
8894         float f1, f2, *c;
8895         float color4f[6*4];
8896
8897         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);
8898
8899         // this is only called once per entity so numsurfaces is always 1, and
8900         // surfacelist is always {0}, so this code does not handle batches
8901
8902         if (rsurface.ent_flags & RENDER_ADDITIVE)
8903         {
8904                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
8905                 GL_DepthMask(false);
8906         }
8907         else if (rsurface.colormod[3] < 1)
8908         {
8909                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8910                 GL_DepthMask(false);
8911         }
8912         else
8913         {
8914                 GL_BlendFunc(GL_ONE, GL_ZERO);
8915                 GL_DepthMask(true);
8916         }
8917         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8918         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8919         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8920         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8921         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8922         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8923         for (i = 0, c = color4f;i < 6;i++, c += 4)
8924         {
8925                 c[0] *= rsurface.colormod[0];
8926                 c[1] *= rsurface.colormod[1];
8927                 c[2] *= rsurface.colormod[2];
8928                 c[3] *= rsurface.colormod[3];
8929         }
8930         if (r_refdef.fogenabled)
8931         {
8932                 for (i = 0, c = color4f;i < 6;i++, c += 4)
8933                 {
8934                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
8935                         f2 = 1 - f1;
8936                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8937                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8938                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8939                 }
8940         }
8941         R_Mesh_ResetTextureState();
8942         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
8943         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
8944 }
8945
8946 void R_DrawNoModel(entity_render_t *ent)
8947 {
8948         vec3_t org;
8949         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8950         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8951                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8952         else
8953                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8954 }
8955
8956 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8957 {
8958         vec3_t right1, right2, diff, normal;
8959
8960         VectorSubtract (org2, org1, normal);
8961
8962         // calculate 'right' vector for start
8963         VectorSubtract (r_refdef.view.origin, org1, diff);
8964         CrossProduct (normal, diff, right1);
8965         VectorNormalize (right1);
8966
8967         // calculate 'right' vector for end
8968         VectorSubtract (r_refdef.view.origin, org2, diff);
8969         CrossProduct (normal, diff, right2);
8970         VectorNormalize (right2);
8971
8972         vert[ 0] = org1[0] + width * right1[0];
8973         vert[ 1] = org1[1] + width * right1[1];
8974         vert[ 2] = org1[2] + width * right1[2];
8975         vert[ 3] = org1[0] - width * right1[0];
8976         vert[ 4] = org1[1] - width * right1[1];
8977         vert[ 5] = org1[2] - width * right1[2];
8978         vert[ 6] = org2[0] - width * right2[0];
8979         vert[ 7] = org2[1] - width * right2[1];
8980         vert[ 8] = org2[2] - width * right2[2];
8981         vert[ 9] = org2[0] + width * right2[0];
8982         vert[10] = org2[1] + width * right2[1];
8983         vert[11] = org2[2] + width * right2[2];
8984 }
8985
8986 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)
8987 {
8988         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8989         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8990         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8991         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8992         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8993         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8994         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8995         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8996         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8997         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8998         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8999         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
9000 }
9001
9002 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
9003 {
9004         int i;
9005         float *vertex3f;
9006         float v[3];
9007         VectorSet(v, x, y, z);
9008         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
9009                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
9010                         break;
9011         if (i == mesh->numvertices)
9012         {
9013                 if (mesh->numvertices < mesh->maxvertices)
9014                 {
9015                         VectorCopy(v, vertex3f);
9016                         mesh->numvertices++;
9017                 }
9018                 return mesh->numvertices;
9019         }
9020         else
9021                 return i;
9022 }
9023
9024 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
9025 {
9026         int i;
9027         int *e, element[3];
9028         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9029         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9030         e = mesh->element3i + mesh->numtriangles * 3;
9031         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
9032         {
9033                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
9034                 if (mesh->numtriangles < mesh->maxtriangles)
9035                 {
9036                         *e++ = element[0];
9037                         *e++ = element[1];
9038                         *e++ = element[2];
9039                         mesh->numtriangles++;
9040                 }
9041                 element[1] = element[2];
9042         }
9043 }
9044
9045 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
9046 {
9047         int i;
9048         int *e, element[3];
9049         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9050         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9051         e = mesh->element3i + mesh->numtriangles * 3;
9052         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
9053         {
9054                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
9055                 if (mesh->numtriangles < mesh->maxtriangles)
9056                 {
9057                         *e++ = element[0];
9058                         *e++ = element[1];
9059                         *e++ = element[2];
9060                         mesh->numtriangles++;
9061                 }
9062                 element[1] = element[2];
9063         }
9064 }
9065
9066 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
9067 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
9068 {
9069         int planenum, planenum2;
9070         int w;
9071         int tempnumpoints;
9072         mplane_t *plane, *plane2;
9073         double maxdist;
9074         double temppoints[2][256*3];
9075         // figure out how large a bounding box we need to properly compute this brush
9076         maxdist = 0;
9077         for (w = 0;w < numplanes;w++)
9078                 maxdist = max(maxdist, fabs(planes[w].dist));
9079         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
9080         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
9081         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
9082         {
9083                 w = 0;
9084                 tempnumpoints = 4;
9085                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
9086                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
9087                 {
9088                         if (planenum2 == planenum)
9089                                 continue;
9090                         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);
9091                         w = !w;
9092                 }
9093                 if (tempnumpoints < 3)
9094                         continue;
9095                 // generate elements forming a triangle fan for this polygon
9096                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
9097         }
9098 }
9099
9100 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)
9101 {
9102         texturelayer_t *layer;
9103         layer = t->currentlayers + t->currentnumlayers++;
9104         layer->type = type;
9105         layer->depthmask = depthmask;
9106         layer->blendfunc1 = blendfunc1;
9107         layer->blendfunc2 = blendfunc2;
9108         layer->texture = texture;
9109         layer->texmatrix = *matrix;
9110         layer->color[0] = r;
9111         layer->color[1] = g;
9112         layer->color[2] = b;
9113         layer->color[3] = a;
9114 }
9115
9116 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
9117 {
9118         double index, f;
9119         index = parms[2] + r_refdef.scene.time * parms[3];
9120         index -= floor(index);
9121         switch (func)
9122         {
9123         default:
9124         case Q3WAVEFUNC_NONE:
9125         case Q3WAVEFUNC_NOISE:
9126         case Q3WAVEFUNC_COUNT:
9127                 f = 0;
9128                 break;
9129         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
9130         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
9131         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
9132         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
9133         case Q3WAVEFUNC_TRIANGLE:
9134                 index *= 4;
9135                 f = index - floor(index);
9136                 if (index < 1)
9137                         f = f;
9138                 else if (index < 2)
9139                         f = 1 - f;
9140                 else if (index < 3)
9141                         f = -f;
9142                 else
9143                         f = -(1 - f);
9144                 break;
9145         }
9146         return (float)(parms[0] + parms[1] * f);
9147 }
9148
9149 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
9150 {
9151         int w, h, idx;
9152         float f;
9153         float tcmat[12];
9154         matrix4x4_t matrix, temp;
9155         switch(tcmod->tcmod)
9156         {
9157                 case Q3TCMOD_COUNT:
9158                 case Q3TCMOD_NONE:
9159                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9160                                 matrix = r_waterscrollmatrix;
9161                         else
9162                                 matrix = identitymatrix;
9163                         break;
9164                 case Q3TCMOD_ENTITYTRANSLATE:
9165                         // this is used in Q3 to allow the gamecode to control texcoord
9166                         // scrolling on the entity, which is not supported in darkplaces yet.
9167                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
9168                         break;
9169                 case Q3TCMOD_ROTATE:
9170                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
9171                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
9172                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
9173                         break;
9174                 case Q3TCMOD_SCALE:
9175                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
9176                         break;
9177                 case Q3TCMOD_SCROLL:
9178                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
9179                         break;
9180                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
9181                         w = (int) tcmod->parms[0];
9182                         h = (int) tcmod->parms[1];
9183                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
9184                         f = f - floor(f);
9185                         idx = (int) floor(f * w * h);
9186                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
9187                         break;
9188                 case Q3TCMOD_STRETCH:
9189                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
9190                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
9191                         break;
9192                 case Q3TCMOD_TRANSFORM:
9193                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
9194                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
9195                         VectorSet(tcmat +  6, 0                   , 0                , 1);
9196                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
9197                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
9198                         break;
9199                 case Q3TCMOD_TURBULENT:
9200                         // this is handled in the RSurf_PrepareVertices function
9201                         matrix = identitymatrix;
9202                         break;
9203         }
9204         temp = *texmatrix;
9205         Matrix4x4_Concat(texmatrix, &matrix, &temp);
9206 }
9207
9208 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
9209 {
9210         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
9211         char name[MAX_QPATH];
9212         skinframe_t *skinframe;
9213         unsigned char pixels[296*194];
9214         strlcpy(cache->name, skinname, sizeof(cache->name));
9215         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
9216         if (developer_loading.integer)
9217                 Con_Printf("loading %s\n", name);
9218         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
9219         if (!skinframe || !skinframe->base)
9220         {
9221                 unsigned char *f;
9222                 fs_offset_t filesize;
9223                 skinframe = NULL;
9224                 f = FS_LoadFile(name, tempmempool, true, &filesize);
9225                 if (f)
9226                 {
9227                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
9228                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
9229                         Mem_Free(f);
9230                 }
9231         }
9232         cache->skinframe = skinframe;
9233 }
9234
9235 texture_t *R_GetCurrentTexture(texture_t *t)
9236 {
9237         int i;
9238         const entity_render_t *ent = rsurface.entity;
9239         dp_model_t *model = ent->model;
9240         q3shaderinfo_layer_tcmod_t *tcmod;
9241
9242         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
9243                 return t->currentframe;
9244         t->update_lastrenderframe = r_textureframe;
9245         t->update_lastrenderentity = (void *)ent;
9246
9247         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
9248                 t->camera_entity = ent->entitynumber;
9249         else
9250                 t->camera_entity = 0;
9251
9252         // switch to an alternate material if this is a q1bsp animated material
9253         {
9254                 texture_t *texture = t;
9255                 int s = rsurface.ent_skinnum;
9256                 if ((unsigned int)s >= (unsigned int)model->numskins)
9257                         s = 0;
9258                 if (model->skinscenes)
9259                 {
9260                         if (model->skinscenes[s].framecount > 1)
9261                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
9262                         else
9263                                 s = model->skinscenes[s].firstframe;
9264                 }
9265                 if (s > 0)
9266                         t = t + s * model->num_surfaces;
9267                 if (t->animated)
9268                 {
9269                         // use an alternate animation if the entity's frame is not 0,
9270                         // and only if the texture has an alternate animation
9271                         if (rsurface.ent_alttextures && t->anim_total[1])
9272                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
9273                         else
9274                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
9275                 }
9276                 texture->currentframe = t;
9277         }
9278
9279         // update currentskinframe to be a qw skin or animation frame
9280         if (rsurface.ent_qwskin >= 0)
9281         {
9282                 i = rsurface.ent_qwskin;
9283                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
9284                 {
9285                         r_qwskincache_size = cl.maxclients;
9286                         if (r_qwskincache)
9287                                 Mem_Free(r_qwskincache);
9288                         r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
9289                 }
9290                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
9291                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
9292                 t->currentskinframe = r_qwskincache[i].skinframe;
9293                 if (t->currentskinframe == NULL)
9294                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9295         }
9296         else if (t->numskinframes >= 2)
9297                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9298         if (t->backgroundnumskinframes >= 2)
9299                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
9300
9301         t->currentmaterialflags = t->basematerialflags;
9302         t->currentalpha = rsurface.colormod[3];
9303         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
9304                 t->currentalpha *= r_wateralpha.value;
9305         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
9306                 t->currentalpha *= t->r_water_wateralpha;
9307         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
9308                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
9309         if (!(rsurface.ent_flags & RENDER_LIGHT))
9310                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
9311         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
9312         {
9313                 // pick a model lighting mode
9314                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
9315                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
9316                 else
9317                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
9318         }
9319         if (rsurface.ent_flags & RENDER_ADDITIVE)
9320                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9321         else if (t->currentalpha < 1)
9322                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9323         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
9324                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
9325         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
9326                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
9327         if (t->backgroundnumskinframes)
9328                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
9329         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
9330         {
9331                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
9332                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
9333         }
9334         else
9335                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
9336         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
9337                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
9338
9339         // there is no tcmod
9340         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9341         {
9342                 t->currenttexmatrix = r_waterscrollmatrix;
9343                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
9344         }
9345         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
9346         {
9347                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
9348                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
9349         }
9350
9351         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9352                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
9353         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9354                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
9355
9356         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
9357         if (t->currentskinframe->qpixels)
9358                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
9359         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
9360         if (!t->basetexture)
9361                 t->basetexture = r_texture_notexture;
9362         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
9363         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
9364         t->nmaptexture = t->currentskinframe->nmap;
9365         if (!t->nmaptexture)
9366                 t->nmaptexture = r_texture_blanknormalmap;
9367         t->glosstexture = r_texture_black;
9368         t->glowtexture = t->currentskinframe->glow;
9369         t->fogtexture = t->currentskinframe->fog;
9370         t->reflectmasktexture = t->currentskinframe->reflect;
9371         if (t->backgroundnumskinframes)
9372         {
9373                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
9374                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
9375                 t->backgroundglosstexture = r_texture_black;
9376                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
9377                 if (!t->backgroundnmaptexture)
9378                         t->backgroundnmaptexture = r_texture_blanknormalmap;
9379         }
9380         else
9381         {
9382                 t->backgroundbasetexture = r_texture_white;
9383                 t->backgroundnmaptexture = r_texture_blanknormalmap;
9384                 t->backgroundglosstexture = r_texture_black;
9385                 t->backgroundglowtexture = NULL;
9386         }
9387         t->specularpower = r_shadow_glossexponent.value;
9388         // TODO: store reference values for these in the texture?
9389         t->specularscale = 0;
9390         if (r_shadow_gloss.integer > 0)
9391         {
9392                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
9393                 {
9394                         if (r_shadow_glossintensity.value > 0)
9395                         {
9396                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
9397                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
9398                                 t->specularscale = r_shadow_glossintensity.value;
9399                         }
9400                 }
9401                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
9402                 {
9403                         t->glosstexture = r_texture_white;
9404                         t->backgroundglosstexture = r_texture_white;
9405                         t->specularscale = r_shadow_gloss2intensity.value;
9406                         t->specularpower = r_shadow_gloss2exponent.value;
9407                 }
9408         }
9409         t->specularscale *= t->specularscalemod;
9410         t->specularpower *= t->specularpowermod;
9411
9412         // lightmaps mode looks bad with dlights using actual texturing, so turn
9413         // off the colormap and glossmap, but leave the normalmap on as it still
9414         // accurately represents the shading involved
9415         if (gl_lightmaps.integer)
9416         {
9417                 t->basetexture = r_texture_grey128;
9418                 t->pantstexture = r_texture_black;
9419                 t->shirttexture = r_texture_black;
9420                 t->nmaptexture = r_texture_blanknormalmap;
9421                 t->glosstexture = r_texture_black;
9422                 t->glowtexture = NULL;
9423                 t->fogtexture = NULL;
9424                 t->reflectmasktexture = NULL;
9425                 t->backgroundbasetexture = NULL;
9426                 t->backgroundnmaptexture = r_texture_blanknormalmap;
9427                 t->backgroundglosstexture = r_texture_black;
9428                 t->backgroundglowtexture = NULL;
9429                 t->specularscale = 0;
9430                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
9431         }
9432
9433         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
9434         VectorClear(t->dlightcolor);
9435         t->currentnumlayers = 0;
9436         if (t->currentmaterialflags & MATERIALFLAG_WALL)
9437         {
9438                 int blendfunc1, blendfunc2;
9439                 qboolean depthmask;
9440                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
9441                 {
9442                         blendfunc1 = GL_SRC_ALPHA;
9443                         blendfunc2 = GL_ONE;
9444                 }
9445                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
9446                 {
9447                         blendfunc1 = GL_SRC_ALPHA;
9448                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
9449                 }
9450                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9451                 {
9452                         blendfunc1 = t->customblendfunc[0];
9453                         blendfunc2 = t->customblendfunc[1];
9454                 }
9455                 else
9456                 {
9457                         blendfunc1 = GL_ONE;
9458                         blendfunc2 = GL_ZERO;
9459                 }
9460                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
9461                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9462                 {
9463                         // fullbright is not affected by r_refdef.lightmapintensity
9464                         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]);
9465                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9466                                 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]);
9467                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9468                                 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]);
9469                 }
9470                 else
9471                 {
9472                         vec3_t ambientcolor;
9473                         float colorscale;
9474                         // set the color tint used for lights affecting this surface
9475                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
9476                         colorscale = 2;
9477                         // q3bsp has no lightmap updates, so the lightstylevalue that
9478                         // would normally be baked into the lightmap must be
9479                         // applied to the color
9480                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
9481                         if (model->type == mod_brushq3)
9482                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
9483                         colorscale *= r_refdef.lightmapintensity;
9484                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
9485                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
9486                         // basic lit geometry
9487                         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]);
9488                         // add pants/shirt if needed
9489                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9490                                 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]);
9491                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9492                                 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]);
9493                         // now add ambient passes if needed
9494                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
9495                         {
9496                                 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]);
9497                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9498                                         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]);
9499                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9500                                         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]);
9501                         }
9502                 }
9503                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
9504                         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]);
9505                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
9506                 {
9507                         // if this is opaque use alpha blend which will darken the earlier
9508                         // passes cheaply.
9509                         //
9510                         // if this is an alpha blended material, all the earlier passes
9511                         // were darkened by fog already, so we only need to add the fog
9512                         // color ontop through the fog mask texture
9513                         //
9514                         // if this is an additive blended material, all the earlier passes
9515                         // were darkened by fog already, and we should not add fog color
9516                         // (because the background was not darkened, there is no fog color
9517                         // that was lost behind it).
9518                         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]);
9519                 }
9520         }
9521
9522         return t->currentframe;
9523 }
9524
9525 rsurfacestate_t rsurface;
9526
9527 void R_Mesh_ResizeArrays(int newvertices)
9528 {
9529         unsigned char *base;
9530         size_t size;
9531         if (rsurface.array_size >= newvertices)
9532                 return;
9533         if (rsurface.array_base)
9534                 Mem_Free(rsurface.array_base);
9535         rsurface.array_size = (newvertices + 1023) & ~1023;
9536         size = 0;
9537         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
9538         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
9539         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
9540         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
9541         size += rsurface.array_size * sizeof(float[3]);
9542         size += rsurface.array_size * sizeof(float[3]);
9543         size += rsurface.array_size * sizeof(float[3]);
9544         size += rsurface.array_size * sizeof(float[3]);
9545         size += rsurface.array_size * sizeof(float[3]);
9546         size += rsurface.array_size * sizeof(float[3]);
9547         size += rsurface.array_size * sizeof(float[3]);
9548         size += rsurface.array_size * sizeof(float[3]);
9549         size += rsurface.array_size * sizeof(float[4]);
9550         size += rsurface.array_size * sizeof(float[2]);
9551         size += rsurface.array_size * sizeof(float[2]);
9552         size += rsurface.array_size * sizeof(float[4]);
9553         size += rsurface.array_size * sizeof(int[3]);
9554         size += rsurface.array_size * sizeof(unsigned short[3]);
9555         rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
9556         rsurface.array_modelvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
9557         rsurface.array_batchvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
9558         rsurface.array_modelvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
9559         rsurface.array_batchvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
9560         rsurface.array_modelvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
9561         rsurface.array_modelsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
9562         rsurface.array_modeltvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
9563         rsurface.array_modelnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
9564         rsurface.array_batchvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
9565         rsurface.array_batchsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
9566         rsurface.array_batchtvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
9567         rsurface.array_batchnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
9568         rsurface.array_batchlightmapcolor4f    = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
9569         rsurface.array_batchtexcoordtexture2f  = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
9570         rsurface.array_batchtexcoordlightmap2f = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
9571         rsurface.array_passcolor4f             = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
9572         rsurface.array_batchelement3i          = (int                *)base;base += rsurface.array_size * sizeof(int[3]);
9573         rsurface.array_batchelement3s          = (unsigned short     *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
9574 }
9575
9576 void RSurf_ActiveWorldEntity(void)
9577 {
9578         dp_model_t *model = r_refdef.scene.worldmodel;
9579         //if (rsurface.entity == r_refdef.scene.worldentity)
9580         //      return;
9581         rsurface.entity = r_refdef.scene.worldentity;
9582         rsurface.skeleton = NULL;
9583         rsurface.ent_skinnum = 0;
9584         rsurface.ent_qwskin = -1;
9585         rsurface.ent_shadertime = 0;
9586         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
9587         if (rsurface.array_size < model->surfmesh.num_vertices)
9588                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9589         rsurface.matrix = identitymatrix;
9590         rsurface.inversematrix = identitymatrix;
9591         rsurface.matrixscale = 1;
9592         rsurface.inversematrixscale = 1;
9593         R_EntityMatrix(&identitymatrix);
9594         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
9595         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
9596         rsurface.fograngerecip = r_refdef.fograngerecip;
9597         rsurface.fogheightfade = r_refdef.fogheightfade;
9598         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
9599         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9600         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9601         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9602         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9603         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9604         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9605         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
9606         rsurface.colormod[3] = 1;
9607         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);
9608         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9609         rsurface.frameblend[0].lerp = 1;
9610         rsurface.ent_alttextures = false;
9611         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9612         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9613         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
9614         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9615         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9616         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9617         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9618         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9619         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9620         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9621         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9622         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
9623         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9624         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9625         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
9626         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9627         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9628         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
9629         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9630         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9631         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
9632         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9633         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9634         rsurface.modelelement3i = model->surfmesh.data_element3i;
9635         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
9636         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
9637         rsurface.modelelement3s = model->surfmesh.data_element3s;
9638         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
9639         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
9640         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9641         rsurface.modelnumvertices = model->surfmesh.num_vertices;
9642         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
9643         rsurface.modelsurfaces = model->data_surfaces;
9644         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
9645         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
9646         rsurface.modelvertexposition = model->surfmesh.vertexposition;
9647         rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
9648         rsurface.modelgeneratedvertex = false;
9649         rsurface.batchgeneratedvertex = false;
9650         rsurface.batchfirstvertex = 0;
9651         rsurface.batchnumvertices = 0;
9652         rsurface.batchfirsttriangle = 0;
9653         rsurface.batchnumtriangles = 0;
9654         rsurface.batchvertex3f  = NULL;
9655         rsurface.batchvertex3f_vertexbuffer = NULL;
9656         rsurface.batchvertex3f_bufferoffset = 0;
9657         rsurface.batchsvector3f = NULL;
9658         rsurface.batchsvector3f_vertexbuffer = NULL;
9659         rsurface.batchsvector3f_bufferoffset = 0;
9660         rsurface.batchtvector3f = NULL;
9661         rsurface.batchtvector3f_vertexbuffer = NULL;
9662         rsurface.batchtvector3f_bufferoffset = 0;
9663         rsurface.batchnormal3f  = NULL;
9664         rsurface.batchnormal3f_vertexbuffer = NULL;
9665         rsurface.batchnormal3f_bufferoffset = 0;
9666         rsurface.batchlightmapcolor4f = NULL;
9667         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9668         rsurface.batchlightmapcolor4f_bufferoffset = 0;
9669         rsurface.batchtexcoordtexture2f = NULL;
9670         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9671         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9672         rsurface.batchtexcoordlightmap2f = NULL;
9673         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9674         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9675         rsurface.batchvertexmesh = NULL;
9676         rsurface.batchvertexmeshbuffer = NULL;
9677         rsurface.batchvertexposition = NULL;
9678         rsurface.batchvertexpositionbuffer = NULL;
9679         rsurface.batchelement3i = NULL;
9680         rsurface.batchelement3i_indexbuffer = NULL;
9681         rsurface.batchelement3i_bufferoffset = 0;
9682         rsurface.batchelement3s = NULL;
9683         rsurface.batchelement3s_indexbuffer = NULL;
9684         rsurface.batchelement3s_bufferoffset = 0;
9685         rsurface.passcolor4f = NULL;
9686         rsurface.passcolor4f_vertexbuffer = NULL;
9687         rsurface.passcolor4f_bufferoffset = 0;
9688 }
9689
9690 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
9691 {
9692         dp_model_t *model = ent->model;
9693         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
9694         //      return;
9695         rsurface.entity = (entity_render_t *)ent;
9696         rsurface.skeleton = ent->skeleton;
9697         rsurface.ent_skinnum = ent->skinnum;
9698         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;
9699         rsurface.ent_shadertime = ent->shadertime;
9700         rsurface.ent_flags = ent->flags;
9701         if (rsurface.array_size < model->surfmesh.num_vertices)
9702                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9703         rsurface.matrix = ent->matrix;
9704         rsurface.inversematrix = ent->inversematrix;
9705         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9706         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9707         R_EntityMatrix(&rsurface.matrix);
9708         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9709         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9710         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9711         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9712         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9713         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9714         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
9715         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
9716         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
9717         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
9718         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
9719         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
9720         rsurface.colormod[3] = ent->alpha;
9721         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
9722         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
9723         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
9724         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9725         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9726         if (ent->model->brush.submodel && !prepass)
9727         {
9728                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
9729                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
9730         }
9731         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
9732         {
9733                 if (ent->animcache_vertex3f && !r_framedata_failed)
9734                 {
9735                         rsurface.modelvertex3f = ent->animcache_vertex3f;
9736                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
9737                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
9738                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
9739                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
9740                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
9741                         rsurface.modelvertexposition = ent->animcache_vertexposition;
9742                         rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
9743                 }
9744                 else if (wanttangents)
9745                 {
9746                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9747                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9748                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9749                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9750                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
9751                         rsurface.modelvertexmesh = NULL;
9752                         rsurface.modelvertexmeshbuffer = NULL;
9753                         rsurface.modelvertexposition = NULL;
9754                         rsurface.modelvertexpositionbuffer = NULL;
9755                 }
9756                 else if (wantnormals)
9757                 {
9758                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9759                         rsurface.modelsvector3f = NULL;
9760                         rsurface.modeltvector3f = NULL;
9761                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9762                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
9763                         rsurface.modelvertexmesh = NULL;
9764                         rsurface.modelvertexmeshbuffer = NULL;
9765                         rsurface.modelvertexposition = NULL;
9766                         rsurface.modelvertexpositionbuffer = NULL;
9767                 }
9768                 else
9769                 {
9770                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9771                         rsurface.modelsvector3f = NULL;
9772                         rsurface.modeltvector3f = NULL;
9773                         rsurface.modelnormal3f = NULL;
9774                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
9775                         rsurface.modelvertexmesh = NULL;
9776                         rsurface.modelvertexmeshbuffer = NULL;
9777                         rsurface.modelvertexposition = NULL;
9778                         rsurface.modelvertexpositionbuffer = NULL;
9779                 }
9780                 rsurface.modelvertex3f_vertexbuffer = 0;
9781                 rsurface.modelvertex3f_bufferoffset = 0;
9782                 rsurface.modelsvector3f_vertexbuffer = 0;
9783                 rsurface.modelsvector3f_bufferoffset = 0;
9784                 rsurface.modeltvector3f_vertexbuffer = 0;
9785                 rsurface.modeltvector3f_bufferoffset = 0;
9786                 rsurface.modelnormal3f_vertexbuffer = 0;
9787                 rsurface.modelnormal3f_bufferoffset = 0;
9788                 rsurface.modelgeneratedvertex = true;
9789         }
9790         else
9791         {
9792                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
9793                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9794                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9795                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9796                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9797                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9798                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9799                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9800                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9801                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
9802                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9803                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9804                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
9805                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
9806                 rsurface.modelvertexposition = model->surfmesh.vertexposition;
9807                 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
9808                 rsurface.modelgeneratedvertex = false;
9809         }
9810         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
9811         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9812         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9813         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
9814         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9815         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9816         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
9817         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9818         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9819         rsurface.modelelement3i = model->surfmesh.data_element3i;
9820         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
9821         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
9822         rsurface.modelelement3s = model->surfmesh.data_element3s;
9823         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
9824         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
9825         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9826         rsurface.modelnumvertices = model->surfmesh.num_vertices;
9827         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
9828         rsurface.modelsurfaces = model->data_surfaces;
9829         rsurface.batchgeneratedvertex = false;
9830         rsurface.batchfirstvertex = 0;
9831         rsurface.batchnumvertices = 0;
9832         rsurface.batchfirsttriangle = 0;
9833         rsurface.batchnumtriangles = 0;
9834         rsurface.batchvertex3f  = NULL;
9835         rsurface.batchvertex3f_vertexbuffer = NULL;
9836         rsurface.batchvertex3f_bufferoffset = 0;
9837         rsurface.batchsvector3f = NULL;
9838         rsurface.batchsvector3f_vertexbuffer = NULL;
9839         rsurface.batchsvector3f_bufferoffset = 0;
9840         rsurface.batchtvector3f = NULL;
9841         rsurface.batchtvector3f_vertexbuffer = NULL;
9842         rsurface.batchtvector3f_bufferoffset = 0;
9843         rsurface.batchnormal3f  = NULL;
9844         rsurface.batchnormal3f_vertexbuffer = NULL;
9845         rsurface.batchnormal3f_bufferoffset = 0;
9846         rsurface.batchlightmapcolor4f = NULL;
9847         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9848         rsurface.batchlightmapcolor4f_bufferoffset = 0;
9849         rsurface.batchtexcoordtexture2f = NULL;
9850         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9851         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9852         rsurface.batchtexcoordlightmap2f = NULL;
9853         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9854         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9855         rsurface.batchvertexmesh = NULL;
9856         rsurface.batchvertexmeshbuffer = NULL;
9857         rsurface.batchvertexposition = NULL;
9858         rsurface.batchvertexpositionbuffer = NULL;
9859         rsurface.batchelement3i = NULL;
9860         rsurface.batchelement3i_indexbuffer = NULL;
9861         rsurface.batchelement3i_bufferoffset = 0;
9862         rsurface.batchelement3s = NULL;
9863         rsurface.batchelement3s_indexbuffer = NULL;
9864         rsurface.batchelement3s_bufferoffset = 0;
9865         rsurface.passcolor4f = NULL;
9866         rsurface.passcolor4f_vertexbuffer = NULL;
9867         rsurface.passcolor4f_bufferoffset = 0;
9868 }
9869
9870 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)
9871 {
9872         int i;
9873
9874         rsurface.entity = r_refdef.scene.worldentity;
9875         rsurface.skeleton = NULL;
9876         rsurface.ent_skinnum = 0;
9877         rsurface.ent_qwskin = -1;
9878         rsurface.ent_shadertime = shadertime;
9879         rsurface.ent_flags = entflags;
9880         rsurface.modelnumvertices = numvertices;
9881         rsurface.modelnumtriangles = numtriangles;
9882         if (rsurface.array_size < rsurface.modelnumvertices)
9883                 R_Mesh_ResizeArrays(rsurface.modelnumvertices);
9884         rsurface.matrix = *matrix;
9885         rsurface.inversematrix = *inversematrix;
9886         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9887         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9888         R_EntityMatrix(&rsurface.matrix);
9889         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9890         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9891         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9892         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9893         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9894         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9895         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9896         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9897         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9898         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9899         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9900         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
9901         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);
9902         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9903         rsurface.frameblend[0].lerp = 1;
9904         rsurface.ent_alttextures = false;
9905         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9906         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9907         if (wanttangents)
9908         {
9909                 rsurface.modelvertex3f = vertex3f;
9910                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
9911                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
9912                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9913         }
9914         else if (wantnormals)
9915         {
9916                 rsurface.modelvertex3f = vertex3f;
9917                 rsurface.modelsvector3f = NULL;
9918                 rsurface.modeltvector3f = NULL;
9919                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9920         }
9921         else
9922         {
9923                 rsurface.modelvertex3f = vertex3f;
9924                 rsurface.modelsvector3f = NULL;
9925                 rsurface.modeltvector3f = NULL;
9926                 rsurface.modelnormal3f = NULL;
9927         }
9928         rsurface.modelvertexmesh = NULL;
9929         rsurface.modelvertexmeshbuffer = NULL;
9930         rsurface.modelvertexposition = NULL;
9931         rsurface.modelvertexpositionbuffer = NULL;
9932         rsurface.modelvertex3f_vertexbuffer = 0;
9933         rsurface.modelvertex3f_bufferoffset = 0;
9934         rsurface.modelsvector3f_vertexbuffer = 0;
9935         rsurface.modelsvector3f_bufferoffset = 0;
9936         rsurface.modeltvector3f_vertexbuffer = 0;
9937         rsurface.modeltvector3f_bufferoffset = 0;
9938         rsurface.modelnormal3f_vertexbuffer = 0;
9939         rsurface.modelnormal3f_bufferoffset = 0;
9940         rsurface.modelgeneratedvertex = true;
9941         rsurface.modellightmapcolor4f  = color4f;
9942         rsurface.modellightmapcolor4f_vertexbuffer = 0;
9943         rsurface.modellightmapcolor4f_bufferoffset = 0;
9944         rsurface.modeltexcoordtexture2f  = texcoord2f;
9945         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
9946         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9947         rsurface.modeltexcoordlightmap2f  = NULL;
9948         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
9949         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9950         rsurface.modelelement3i = element3i;
9951         rsurface.modelelement3i_indexbuffer = NULL;
9952         rsurface.modelelement3i_bufferoffset = 0;
9953         rsurface.modelelement3s = element3s;
9954         rsurface.modelelement3s_indexbuffer = NULL;
9955         rsurface.modelelement3s_bufferoffset = 0;
9956         rsurface.modellightmapoffsets = NULL;
9957         rsurface.modelsurfaces = NULL;
9958         rsurface.batchgeneratedvertex = false;
9959         rsurface.batchfirstvertex = 0;
9960         rsurface.batchnumvertices = 0;
9961         rsurface.batchfirsttriangle = 0;
9962         rsurface.batchnumtriangles = 0;
9963         rsurface.batchvertex3f  = NULL;
9964         rsurface.batchvertex3f_vertexbuffer = NULL;
9965         rsurface.batchvertex3f_bufferoffset = 0;
9966         rsurface.batchsvector3f = NULL;
9967         rsurface.batchsvector3f_vertexbuffer = NULL;
9968         rsurface.batchsvector3f_bufferoffset = 0;
9969         rsurface.batchtvector3f = NULL;
9970         rsurface.batchtvector3f_vertexbuffer = NULL;
9971         rsurface.batchtvector3f_bufferoffset = 0;
9972         rsurface.batchnormal3f  = NULL;
9973         rsurface.batchnormal3f_vertexbuffer = NULL;
9974         rsurface.batchnormal3f_bufferoffset = 0;
9975         rsurface.batchlightmapcolor4f = NULL;
9976         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9977         rsurface.batchlightmapcolor4f_bufferoffset = 0;
9978         rsurface.batchtexcoordtexture2f = NULL;
9979         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9980         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9981         rsurface.batchtexcoordlightmap2f = NULL;
9982         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9983         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9984         rsurface.batchvertexmesh = NULL;
9985         rsurface.batchvertexmeshbuffer = NULL;
9986         rsurface.batchvertexposition = NULL;
9987         rsurface.batchvertexpositionbuffer = NULL;
9988         rsurface.batchelement3i = NULL;
9989         rsurface.batchelement3i_indexbuffer = NULL;
9990         rsurface.batchelement3i_bufferoffset = 0;
9991         rsurface.batchelement3s = NULL;
9992         rsurface.batchelement3s_indexbuffer = NULL;
9993         rsurface.batchelement3s_bufferoffset = 0;
9994         rsurface.passcolor4f = NULL;
9995         rsurface.passcolor4f_vertexbuffer = NULL;
9996         rsurface.passcolor4f_bufferoffset = 0;
9997
9998         if (rsurface.modelnumvertices && rsurface.modelelement3i)
9999         {
10000                 if ((wantnormals || wanttangents) && !normal3f)
10001                 {
10002                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
10003                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10004                 }
10005                 if (wanttangents && !svector3f)
10006                 {
10007                         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);
10008                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10009                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10010                 }
10011         }
10012
10013         // now convert arrays into vertexmesh structs
10014         for (i = 0;i < numvertices;i++)
10015         {
10016                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexposition[i].vertex3f);
10017                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexmesh[i].vertex3f);
10018                 if (rsurface.modelsvector3f)
10019                         VectorCopy(rsurface.modelsvector3f + 3*i, rsurface.array_modelvertexmesh[i].svector3f);
10020                 if (rsurface.modeltvector3f)
10021                         VectorCopy(rsurface.modeltvector3f + 3*i, rsurface.array_modelvertexmesh[i].tvector3f);
10022                 if (rsurface.modelnormal3f)
10023                         VectorCopy(rsurface.modelnormal3f + 3*i, rsurface.array_modelvertexmesh[i].normal3f);
10024                 if (rsurface.modellightmapcolor4f)
10025                         Vector4Scale(rsurface.modellightmapcolor4f + 4*i, 255.0f, rsurface.array_modelvertexmesh[i].color4ub);
10026                 if (rsurface.modeltexcoordtexture2f)
10027                         Vector2Copy(rsurface.modeltexcoordtexture2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordtexture2f);
10028                 if (rsurface.modeltexcoordlightmap2f)
10029                         Vector2Copy(rsurface.modeltexcoordlightmap2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordlightmap2f);
10030         }
10031 }
10032
10033 float RSurf_FogPoint(const float *v)
10034 {
10035         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10036         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
10037         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
10038         float FogHeightFade = r_refdef.fogheightfade;
10039         float fogfrac;
10040         unsigned int fogmasktableindex;
10041         if (r_refdef.fogplaneviewabove)
10042                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10043         else
10044                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10045         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
10046         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10047 }
10048
10049 float RSurf_FogVertex(const float *v)
10050 {
10051         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10052         float FogPlaneViewDist = rsurface.fogplaneviewdist;
10053         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
10054         float FogHeightFade = rsurface.fogheightfade;
10055         float fogfrac;
10056         unsigned int fogmasktableindex;
10057         if (r_refdef.fogplaneviewabove)
10058                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10059         else
10060                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10061         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
10062         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10063 }
10064
10065 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
10066 {
10067         int i;
10068         for (i = 0;i < numelements;i++)
10069                 outelement3i[i] = inelement3i[i] + adjust;
10070 }
10071
10072 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
10073 extern cvar_t gl_vbo;
10074 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
10075 {
10076         int deformindex;
10077         int firsttriangle;
10078         int numtriangles;
10079         int firstvertex;
10080         int endvertex;
10081         int numvertices;
10082         int surfacefirsttriangle;
10083         int surfacenumtriangles;
10084         int surfacefirstvertex;
10085         int surfaceendvertex;
10086         int surfacenumvertices;
10087         int surfaceadjustvertex;
10088         int needsupdate;
10089         int i, j;
10090         qboolean gaps;
10091         qboolean dynamicvertex;
10092         float amplitude;
10093         float animpos;
10094         float scale;
10095         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
10096         float waveparms[4];
10097         q3shaderinfo_deform_t *deform;
10098         const msurface_t *surface, *firstsurface;
10099         r_vertexposition_t *vertexposition;
10100         r_vertexmesh_t *vertexmesh;
10101         if (!texturenumsurfaces)
10102                 return;
10103         // find vertex range of this surface batch
10104         gaps = false;
10105         firstsurface = texturesurfacelist[0];
10106         firsttriangle = firstsurface->num_firsttriangle;
10107         numtriangles = 0;
10108         firstvertex = endvertex = firstsurface->num_firstvertex;
10109         for (i = 0;i < texturenumsurfaces;i++)
10110         {
10111                 surface = texturesurfacelist[i];
10112                 if (surface != firstsurface + i)
10113                         gaps = true;
10114                 surfacefirstvertex = surface->num_firstvertex;
10115                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
10116                 surfacenumtriangles = surface->num_triangles;
10117                 if (firstvertex > surfacefirstvertex)
10118                         firstvertex = surfacefirstvertex;
10119                 if (endvertex < surfaceendvertex)
10120                         endvertex = surfaceendvertex;
10121                 numtriangles += surfacenumtriangles;
10122         }
10123         if (!numtriangles)
10124                 return;
10125
10126         // we now know the vertex range used, and if there are any gaps in it
10127         rsurface.batchfirstvertex = firstvertex;
10128         rsurface.batchnumvertices = endvertex - firstvertex;
10129         rsurface.batchfirsttriangle = firsttriangle;
10130         rsurface.batchnumtriangles = numtriangles;
10131
10132         // this variable holds flags for which properties have been updated that
10133         // may require regenerating vertexmesh or vertexposition arrays...
10134         needsupdate = 0;
10135
10136         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
10137                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
10138         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
10139         {
10140                 switch (deform->deform)
10141                 {
10142                 default:
10143                 case Q3DEFORM_PROJECTIONSHADOW:
10144                 case Q3DEFORM_TEXT0:
10145                 case Q3DEFORM_TEXT1:
10146                 case Q3DEFORM_TEXT2:
10147                 case Q3DEFORM_TEXT3:
10148                 case Q3DEFORM_TEXT4:
10149                 case Q3DEFORM_TEXT5:
10150                 case Q3DEFORM_TEXT6:
10151                 case Q3DEFORM_TEXT7:
10152                 case Q3DEFORM_NONE:
10153                         break;
10154                 case Q3DEFORM_AUTOSPRITE:
10155                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10156                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10157                         break;
10158                 case Q3DEFORM_AUTOSPRITE2:
10159                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10160                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10161                         break;
10162                 case Q3DEFORM_NORMAL:
10163                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10164                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10165                         break;
10166                 case Q3DEFORM_WAVE:
10167                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10168                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10169                         break;
10170                 case Q3DEFORM_BULGE:
10171                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10172                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10173                         break;
10174                 case Q3DEFORM_MOVE:
10175                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
10176                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
10177                         break;
10178                 }
10179         }
10180         switch(rsurface.texture->tcgen.tcgen)
10181         {
10182         default:
10183         case Q3TCGEN_TEXTURE:
10184                 break;
10185         case Q3TCGEN_LIGHTMAP:
10186                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
10187                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
10188                 break;
10189         case Q3TCGEN_VECTOR:
10190                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
10191                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
10192                 break;
10193         case Q3TCGEN_ENVIRONMENT:
10194                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
10195                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
10196                 break;
10197         }
10198         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10199         {
10200                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
10201                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
10202         }
10203
10204         // check if any dynamic vertex processing must occur
10205         dynamicvertex = false;
10206
10207         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
10208         {
10209                 dynamicvertex = true;
10210                 batchneed |= BATCHNEED_NOGAPS;
10211                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
10212         }
10213
10214         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
10215         {
10216                 dynamicvertex = true;
10217                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
10218                 needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
10219         }
10220
10221         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
10222         {
10223                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
10224                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
10225                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
10226                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
10227                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
10228                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
10229                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
10230         }
10231
10232         // when the model data has no vertex buffer (dynamic mesh), we need to
10233         // eliminate gaps
10234         if (!rsurface.modelvertexmeshbuffer || (!gl_vbo.integer && !vid.forcevbo))
10235                 batchneed |= BATCHNEED_NOGAPS;
10236
10237         // if needsupdate, we have to do a dynamic vertex batch for sure
10238         if (needsupdate & batchneed)
10239                 dynamicvertex = true;
10240
10241         // see if we need to build vertexmesh from arrays
10242         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
10243                 dynamicvertex = true;
10244
10245         // see if we need to build vertexposition from arrays
10246         if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
10247                 dynamicvertex = true;
10248
10249         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
10250         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
10251                 dynamicvertex = true;
10252
10253         // if there is a chance of animated vertex colors, it's a dynamic batch
10254         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
10255                 dynamicvertex = true;
10256
10257         rsurface.batchvertex3f = rsurface.modelvertex3f;
10258         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
10259         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
10260         rsurface.batchsvector3f = rsurface.modelsvector3f;
10261         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
10262         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
10263         rsurface.batchtvector3f = rsurface.modeltvector3f;
10264         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
10265         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
10266         rsurface.batchnormal3f = rsurface.modelnormal3f;
10267         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
10268         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
10269         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
10270         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
10271         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
10272         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
10273         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
10274         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
10275         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
10276         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
10277         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
10278         rsurface.batchvertexposition = rsurface.modelvertexposition;
10279         rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
10280         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
10281         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
10282         rsurface.batchelement3i = rsurface.modelelement3i;
10283         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
10284         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
10285         rsurface.batchelement3s = rsurface.modelelement3s;
10286         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
10287         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
10288
10289         // if any dynamic vertex processing has to occur in software, we copy the
10290         // entire surface list together before processing to rebase the vertices
10291         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
10292         //
10293         // if any gaps exist and we do not have a static vertex buffer, we have to
10294         // copy the surface list together to avoid wasting upload bandwidth on the
10295         // vertices in the gaps.
10296         //
10297         // if gaps exist and we have a static vertex buffer, we still have to
10298         // combine the index buffer ranges into one dynamic index buffer.
10299         //
10300         // in all cases we end up with data that can be drawn in one call.
10301
10302         if (!dynamicvertex)
10303         {
10304                 // static vertex data, just set pointers...
10305                 rsurface.batchgeneratedvertex = false;
10306                 // if there are gaps, we want to build a combined index buffer,
10307                 // otherwise use the original static buffer with an appropriate offset
10308                 if (gaps)
10309                 {
10310                         firsttriangle = 0;
10311                         numtriangles = 0;
10312                         for (i = 0;i < texturenumsurfaces;i++)
10313                         {
10314                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
10315                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
10316                                 memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
10317                                 numtriangles += surfacenumtriangles;
10318                         }
10319                         rsurface.batchelement3i = rsurface.array_batchelement3i;
10320                         rsurface.batchelement3i_indexbuffer = NULL;
10321                         rsurface.batchelement3i_bufferoffset = 0;
10322                         rsurface.batchelement3s = NULL;
10323                         rsurface.batchelement3s_indexbuffer = NULL;
10324                         rsurface.batchelement3s_bufferoffset = 0;
10325                         if (endvertex <= 65536)
10326                         {
10327                                 rsurface.batchelement3s = rsurface.array_batchelement3s;
10328                                 for (i = 0;i < numtriangles*3;i++)
10329                                         rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
10330                         }
10331                         rsurface.batchfirsttriangle = firsttriangle;
10332                         rsurface.batchnumtriangles = numtriangles;
10333                 }
10334                 return;
10335         }
10336
10337         // something needs software processing, do it for real...
10338         // we only directly handle interleaved array data in this case...
10339         rsurface.batchgeneratedvertex = true;
10340
10341         // now copy the vertex data into a combined array and make an index array
10342         // (this is what Quake3 does all the time)
10343         //if (gaps || rsurface.batchfirstvertex)
10344         {
10345                 rsurface.batchvertexposition = NULL;
10346                 rsurface.batchvertexpositionbuffer = NULL;
10347                 rsurface.batchvertexmesh = NULL;
10348                 rsurface.batchvertexmeshbuffer = NULL;
10349                 rsurface.batchvertex3f = NULL;
10350                 rsurface.batchvertex3f_vertexbuffer = NULL;
10351                 rsurface.batchvertex3f_bufferoffset = 0;
10352                 rsurface.batchsvector3f = NULL;
10353                 rsurface.batchsvector3f_vertexbuffer = NULL;
10354                 rsurface.batchsvector3f_bufferoffset = 0;
10355                 rsurface.batchtvector3f = NULL;
10356                 rsurface.batchtvector3f_vertexbuffer = NULL;
10357                 rsurface.batchtvector3f_bufferoffset = 0;
10358                 rsurface.batchnormal3f = NULL;
10359                 rsurface.batchnormal3f_vertexbuffer = NULL;
10360                 rsurface.batchnormal3f_bufferoffset = 0;
10361                 rsurface.batchlightmapcolor4f = NULL;
10362                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10363                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10364                 rsurface.batchtexcoordtexture2f = NULL;
10365                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10366                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10367                 rsurface.batchtexcoordlightmap2f = NULL;
10368                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10369                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10370                 rsurface.batchelement3i = rsurface.array_batchelement3i;
10371                 rsurface.batchelement3i_indexbuffer = NULL;
10372                 rsurface.batchelement3i_bufferoffset = 0;
10373                 rsurface.batchelement3s = NULL;
10374                 rsurface.batchelement3s_indexbuffer = NULL;
10375                 rsurface.batchelement3s_bufferoffset = 0;
10376                 // we'll only be setting up certain arrays as needed
10377                 if (batchneed & BATCHNEED_VERTEXPOSITION)
10378                         rsurface.batchvertexposition = rsurface.array_batchvertexposition;
10379                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10380                         rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
10381                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
10382                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
10383                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
10384                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
10385                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
10386                 {
10387                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
10388                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
10389                 }
10390                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
10391                         rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
10392                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
10393                         rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
10394                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
10395                         rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
10396                 numvertices = 0;
10397                 numtriangles = 0;
10398                 for (i = 0;i < texturenumsurfaces;i++)
10399                 {
10400                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
10401                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
10402                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
10403                         surfaceadjustvertex = numvertices - surfacefirstvertex;
10404                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
10405                         // copy only the data requested
10406                         if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
10407                                 memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
10408                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
10409                                 memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
10410                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
10411                         {
10412                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
10413                                         memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
10414                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
10415                                         memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
10416                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
10417                                 {
10418                                         memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
10419                                         memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
10420                                 }
10421                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
10422                                         memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
10423                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
10424                                         memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
10425                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
10426                                         memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
10427                         }
10428                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
10429                         numvertices += surfacenumvertices;
10430                         numtriangles += surfacenumtriangles;
10431                 }
10432
10433                 // generate a 16bit index array as well if possible
10434                 // (in general, dynamic batches fit)
10435                 if (numvertices <= 65536)
10436                 {
10437                         rsurface.batchelement3s = rsurface.array_batchelement3s;
10438                         for (i = 0;i < numtriangles*3;i++)
10439                                 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
10440                 }
10441
10442                 // since we've copied everything, the batch now starts at 0
10443                 rsurface.batchfirstvertex = 0;
10444                 rsurface.batchnumvertices = numvertices;
10445                 rsurface.batchfirsttriangle = 0;
10446                 rsurface.batchnumtriangles = numtriangles;
10447         }
10448
10449         // q1bsp surfaces rendered in vertex color mode have to have colors
10450         // calculated based on lightstyles
10451         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
10452         {
10453                 // generate color arrays for the surfaces in this list
10454                 int c[4];
10455                 int scale;
10456                 int size3;
10457                 const int *offsets;
10458                 const unsigned char *lm;
10459                 numvertices = 0;
10460                 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
10461                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10462                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10463                 for (i = 0;i < texturenumsurfaces;i++)
10464                 {
10465                         surface = texturesurfacelist[i];
10466                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
10467                         surfacenumvertices = surface->num_vertices;
10468                         if (surface->lightmapinfo->samples)
10469                         {
10470                                 for (j = 0;j < surfacenumvertices;j++)
10471                                 {
10472                                         lm = surface->lightmapinfo->samples + offsets[j];
10473                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
10474                                         VectorScale(lm, scale, c);
10475                                         if (surface->lightmapinfo->styles[1] != 255)
10476                                         {
10477                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
10478                                                 lm += size3;
10479                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
10480                                                 VectorMA(c, scale, lm, c);
10481                                                 if (surface->lightmapinfo->styles[2] != 255)
10482                                                 {
10483                                                         lm += size3;
10484                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
10485                                                         VectorMA(c, scale, lm, c);
10486                                                         if (surface->lightmapinfo->styles[3] != 255)
10487                                                         {
10488                                                                 lm += size3;
10489                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
10490                                                                 VectorMA(c, scale, lm, c);
10491                                                         }
10492                                                 }
10493                                         }
10494                                         c[0] >>= 15;
10495                                         c[1] >>= 15;
10496                                         c[2] >>= 15;
10497                                         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);
10498                                         numvertices++;
10499                                 }
10500                         }
10501                         else
10502                         {
10503                                 for (j = 0;j < surfacenumvertices;j++)
10504                                 {
10505                                         Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
10506                                         numvertices++;
10507                                 }
10508                         }
10509                 }
10510         }
10511
10512         // if vertices are deformed (sprite flares and things in maps, possibly
10513         // water waves, bulges and other deformations), modify the copied vertices
10514         // in place
10515         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
10516         {
10517                 switch (deform->deform)
10518                 {
10519                 default:
10520                 case Q3DEFORM_PROJECTIONSHADOW:
10521                 case Q3DEFORM_TEXT0:
10522                 case Q3DEFORM_TEXT1:
10523                 case Q3DEFORM_TEXT2:
10524                 case Q3DEFORM_TEXT3:
10525                 case Q3DEFORM_TEXT4:
10526                 case Q3DEFORM_TEXT5:
10527                 case Q3DEFORM_TEXT6:
10528                 case Q3DEFORM_TEXT7:
10529                 case Q3DEFORM_NONE:
10530                         break;
10531                 case Q3DEFORM_AUTOSPRITE:
10532                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
10533                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
10534                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
10535                         VectorNormalize(newforward);
10536                         VectorNormalize(newright);
10537                         VectorNormalize(newup);
10538                         // a single autosprite surface can contain multiple sprites...
10539                         for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
10540                         {
10541                                 VectorClear(center);
10542                                 for (i = 0;i < 4;i++)
10543                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
10544                                 VectorScale(center, 0.25f, center);
10545                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
10546                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
10547                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
10548                                 for (i = 0;i < 4;i++)
10549                                 {
10550                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
10551                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
10552                                 }
10553                         }
10554                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
10555                         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);
10556                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
10557                         rsurface.batchvertex3f_vertexbuffer = NULL;
10558                         rsurface.batchvertex3f_bufferoffset = 0;
10559                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
10560                         rsurface.batchsvector3f_vertexbuffer = NULL;
10561                         rsurface.batchsvector3f_bufferoffset = 0;
10562                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
10563                         rsurface.batchtvector3f_vertexbuffer = NULL;
10564                         rsurface.batchtvector3f_bufferoffset = 0;
10565                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
10566                         rsurface.batchnormal3f_vertexbuffer = NULL;
10567                         rsurface.batchnormal3f_bufferoffset = 0;
10568                         break;
10569                 case Q3DEFORM_AUTOSPRITE2:
10570                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
10571                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
10572                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
10573                         VectorNormalize(newforward);
10574                         VectorNormalize(newright);
10575                         VectorNormalize(newup);
10576                         {
10577                                 const float *v1, *v2;
10578                                 vec3_t start, end;
10579                                 float f, l;
10580                                 struct
10581                                 {
10582                                         float length2;
10583                                         const float *v1;
10584                                         const float *v2;
10585                                 }
10586                                 shortest[2];
10587                                 memset(shortest, 0, sizeof(shortest));
10588                                 // a single autosprite surface can contain multiple sprites...
10589                                 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
10590                                 {
10591                                         VectorClear(center);
10592                                         for (i = 0;i < 4;i++)
10593                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
10594                                         VectorScale(center, 0.25f, center);
10595                                         // find the two shortest edges, then use them to define the
10596                                         // axis vectors for rotating around the central axis
10597                                         for (i = 0;i < 6;i++)
10598                                         {
10599                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
10600                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
10601                                                 l = VectorDistance2(v1, v2);
10602                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
10603                                                 if (v1[2] != v2[2])
10604                                                         l += (1.0f / 1024.0f);
10605                                                 if (shortest[0].length2 > l || i == 0)
10606                                                 {
10607                                                         shortest[1] = shortest[0];
10608                                                         shortest[0].length2 = l;
10609                                                         shortest[0].v1 = v1;
10610                                                         shortest[0].v2 = v2;
10611                                                 }
10612                                                 else if (shortest[1].length2 > l || i == 1)
10613                                                 {
10614                                                         shortest[1].length2 = l;
10615                                                         shortest[1].v1 = v1;
10616                                                         shortest[1].v2 = v2;
10617                                                 }
10618                                         }
10619                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
10620                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
10621                                         // this calculates the right vector from the shortest edge
10622                                         // and the up vector from the edge midpoints
10623                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
10624                                         VectorNormalize(right);
10625                                         VectorSubtract(end, start, up);
10626                                         VectorNormalize(up);
10627                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
10628                                         VectorSubtract(rsurface.localvieworigin, center, forward);
10629                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
10630                                         VectorNegate(forward, forward);
10631                                         VectorReflect(forward, 0, up, forward);
10632                                         VectorNormalize(forward);
10633                                         CrossProduct(up, forward, newright);
10634                                         VectorNormalize(newright);
10635                                         // rotate the quad around the up axis vector, this is made
10636                                         // especially easy by the fact we know the quad is flat,
10637                                         // so we only have to subtract the center position and
10638                                         // measure distance along the right vector, and then
10639                                         // multiply that by the newright vector and add back the
10640                                         // center position
10641                                         // we also need to subtract the old position to undo the
10642                                         // displacement from the center, which we do with a
10643                                         // DotProduct, the subtraction/addition of center is also
10644                                         // optimized into DotProducts here
10645                                         l = DotProduct(right, center);
10646                                         for (i = 0;i < 4;i++)
10647                                         {
10648                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
10649                                                 f = DotProduct(right, v1) - l;
10650                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
10651                                         }
10652                                 }
10653                         }
10654                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
10655                         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);
10656                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
10657                         rsurface.batchvertex3f_vertexbuffer = NULL;
10658                         rsurface.batchvertex3f_bufferoffset = 0;
10659                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
10660                         rsurface.batchsvector3f_vertexbuffer = NULL;
10661                         rsurface.batchsvector3f_bufferoffset = 0;
10662                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
10663                         rsurface.batchtvector3f_vertexbuffer = NULL;
10664                         rsurface.batchtvector3f_bufferoffset = 0;
10665                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
10666                         rsurface.batchnormal3f_vertexbuffer = NULL;
10667                         rsurface.batchnormal3f_bufferoffset = 0;
10668                         break;
10669                 case Q3DEFORM_NORMAL:
10670                         // deform the normals to make reflections wavey
10671                         for (j = 0;j < rsurface.batchnumvertices;j++)
10672                         {
10673                                 float vertex[3];
10674                                 float *normal = rsurface.array_batchnormal3f + 3*j;
10675                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
10676                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
10677                                 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]);
10678                                 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]);
10679                                 VectorNormalize(normal);
10680                         }
10681                         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);
10682                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
10683                         rsurface.batchsvector3f_vertexbuffer = NULL;
10684                         rsurface.batchsvector3f_bufferoffset = 0;
10685                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
10686                         rsurface.batchtvector3f_vertexbuffer = NULL;
10687                         rsurface.batchtvector3f_bufferoffset = 0;
10688                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
10689                         rsurface.batchnormal3f_vertexbuffer = NULL;
10690                         rsurface.batchnormal3f_bufferoffset = 0;
10691                         break;
10692                 case Q3DEFORM_WAVE:
10693                         // deform vertex array to make wavey water and flags and such
10694                         waveparms[0] = deform->waveparms[0];
10695                         waveparms[1] = deform->waveparms[1];
10696                         waveparms[2] = deform->waveparms[2];
10697                         waveparms[3] = deform->waveparms[3];
10698                         // this is how a divisor of vertex influence on deformation
10699                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10700                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10701                         for (j = 0;j < rsurface.batchnumvertices;j++)
10702                         {
10703                                 // if the wavefunc depends on time, evaluate it per-vertex
10704                                 if (waveparms[3])
10705                                 {
10706                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10707                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10708                                 }
10709                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
10710                         }
10711                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
10712                         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);
10713                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
10714                         rsurface.batchvertex3f_vertexbuffer = NULL;
10715                         rsurface.batchvertex3f_bufferoffset = 0;
10716                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
10717                         rsurface.batchsvector3f_vertexbuffer = NULL;
10718                         rsurface.batchsvector3f_bufferoffset = 0;
10719                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
10720                         rsurface.batchtvector3f_vertexbuffer = NULL;
10721                         rsurface.batchtvector3f_bufferoffset = 0;
10722                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
10723                         rsurface.batchnormal3f_vertexbuffer = NULL;
10724                         rsurface.batchnormal3f_bufferoffset = 0;
10725                         break;
10726                 case Q3DEFORM_BULGE:
10727                         // deform vertex array to make the surface have moving bulges
10728                         for (j = 0;j < rsurface.batchnumvertices;j++)
10729                         {
10730                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
10731                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
10732                         }
10733                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
10734                         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);
10735                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
10736                         rsurface.batchvertex3f_vertexbuffer = NULL;
10737                         rsurface.batchvertex3f_bufferoffset = 0;
10738                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
10739                         rsurface.batchsvector3f_vertexbuffer = NULL;
10740                         rsurface.batchsvector3f_bufferoffset = 0;
10741                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
10742                         rsurface.batchtvector3f_vertexbuffer = NULL;
10743                         rsurface.batchtvector3f_bufferoffset = 0;
10744                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
10745                         rsurface.batchnormal3f_vertexbuffer = NULL;
10746                         rsurface.batchnormal3f_bufferoffset = 0;
10747                         break;
10748                 case Q3DEFORM_MOVE:
10749                         // deform vertex array
10750                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10751                         VectorScale(deform->parms, scale, waveparms);
10752                         for (j = 0;j < rsurface.batchnumvertices;j++)
10753                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
10754                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
10755                         rsurface.batchvertex3f_vertexbuffer = NULL;
10756                         rsurface.batchvertex3f_bufferoffset = 0;
10757                         break;
10758                 }
10759         }
10760
10761         // generate texcoords based on the chosen texcoord source
10762         switch(rsurface.texture->tcgen.tcgen)
10763         {
10764         default:
10765         case Q3TCGEN_TEXTURE:
10766                 break;
10767         case Q3TCGEN_LIGHTMAP:
10768                 if (rsurface.batchtexcoordlightmap2f)
10769                         memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
10770                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
10771                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10772                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10773                 break;
10774         case Q3TCGEN_VECTOR:
10775                 for (j = 0;j < rsurface.batchnumvertices;j++)
10776                 {
10777                         rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
10778                         rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
10779                 }
10780                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
10781                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10782                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10783                 break;
10784         case Q3TCGEN_ENVIRONMENT:
10785                 // make environment reflections using a spheremap
10786                 for (j = 0;j < rsurface.batchnumvertices;j++)
10787                 {
10788                         // identical to Q3A's method, but executed in worldspace so
10789                         // carried models can be shiny too
10790
10791                         float viewer[3], d, reflected[3], worldreflected[3];
10792
10793                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10794                         // VectorNormalize(viewer);
10795
10796                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10797
10798                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10799                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10800                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10801                         // note: this is proportinal to viewer, so we can normalize later
10802
10803                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10804                         VectorNormalize(worldreflected);
10805
10806                         // note: this sphere map only uses world x and z!
10807                         // so positive and negative y will LOOK THE SAME.
10808                         rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10809                         rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10810                 }
10811                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
10812                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10813                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10814                 break;
10815         }
10816         // the only tcmod that needs software vertex processing is turbulent, so
10817         // check for it here and apply the changes if needed
10818         // and we only support that as the first one
10819         // (handling a mixture of turbulent and other tcmods would be problematic
10820         //  without punting it entirely to a software path)
10821         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10822         {
10823                 amplitude = rsurface.texture->tcmods[0].parms[1];
10824                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
10825                 for (j = 0;j < rsurface.batchnumvertices;j++)
10826                 {
10827                         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);
10828                         rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10829                 }
10830                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
10831                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10832                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10833         }
10834
10835         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10836         {
10837                 // convert the modified arrays to vertex structs
10838                 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
10839                 rsurface.batchvertexmeshbuffer = NULL;
10840                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10841                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
10842                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10843                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10844                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
10845                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10846                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10847                 {
10848                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
10849                         {
10850                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10851                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10852                         }
10853                 }
10854                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10855                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
10856                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
10857                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10858                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
10859                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10860                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10861                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
10862                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10863         }
10864
10865         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
10866         {
10867                 // convert the modified arrays to vertex structs
10868                 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
10869                 rsurface.batchvertexpositionbuffer = NULL;
10870                 if (sizeof(r_vertexposition_t) == sizeof(float[3]))
10871                         memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
10872                 else
10873                         for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
10874                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
10875         }
10876 }
10877
10878 void RSurf_DrawBatch(void)
10879 {
10880         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);
10881 }
10882
10883 static void RSurf_BindLightmapForBatch(void)
10884 {
10885         switch(vid.renderpath)
10886         {
10887         case RENDERPATH_CGGL:
10888 #ifdef SUPPORTCG
10889                 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , rsurface.lightmaptexture );CHECKCGERROR
10890                 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, rsurface.deluxemaptexture);CHECKCGERROR
10891 #endif
10892                 break;
10893         case RENDERPATH_GL20:
10894                 if (r_glsl_permutation->loc_Texture_Lightmap  >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture );
10895                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, rsurface.deluxemaptexture);
10896                 break;
10897         case RENDERPATH_GL13:
10898         case RENDERPATH_GL11:
10899                 R_Mesh_TexBind(0, rsurface.lightmaptexture);
10900                 break;
10901         }
10902 }
10903
10904 static void RSurf_BindReflectionForBatch(void)
10905 {
10906         // pick the closest matching water plane and bind textures
10907         int planeindex, vertexindex;
10908         float d, bestd;
10909         vec3_t vert;
10910         const float *v;
10911         r_waterstate_waterplane_t *p, *bestp;
10912         bestd = 0;
10913         bestp = NULL;
10914         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
10915         {
10916                 if(p->camera_entity != rsurface.texture->camera_entity)
10917                         continue;
10918                 d = 0;
10919                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10920                 {
10921                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10922                         d += fabs(PlaneDiff(vert, &p->plane));
10923                 }
10924                 if (bestd > d || !bestp)
10925                 {
10926                         bestd = d;
10927                         bestp = p;
10928                 }
10929         }
10930         switch(vid.renderpath)
10931         {
10932         case RENDERPATH_CGGL:
10933 #ifdef SUPPORTCG
10934                 if (r_cg_permutation->fp_Texture_Refraction) {CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR}
10935                 else if (r_cg_permutation->fp_Texture_First) {CG_BindTexture(r_cg_permutation->fp_Texture_First, bestp ? bestp->texture_camera : r_texture_black);CHECKCGERROR}
10936                 if (r_cg_permutation->fp_Texture_Reflection) {CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR}
10937 #endif
10938                 break;
10939         case RENDERPATH_GL20:
10940                 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
10941                 else if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST, bestp ? bestp->texture_camera : r_texture_black);
10942                 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
10943                 break;
10944         case RENDERPATH_GL13:
10945         case RENDERPATH_GL11:
10946                 break;
10947         }
10948 }
10949
10950 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10951 {
10952         int i;
10953         for (i = 0;i < rsurface.batchnumvertices;i++)
10954                 Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10955         rsurface.passcolor4f = rsurface.array_passcolor4f;
10956         rsurface.passcolor4f_vertexbuffer = 0;
10957         rsurface.passcolor4f_bufferoffset = 0;
10958 }
10959
10960 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10961 {
10962         int i;
10963         float f;
10964         const float *v;
10965         const float *c;
10966         float *c2;
10967         if (rsurface.passcolor4f)
10968         {
10969                 // generate color arrays
10970                 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)
10971                 {
10972                         f = RSurf_FogVertex(v);
10973                         c2[0] = c[0] * f;
10974                         c2[1] = c[1] * f;
10975                         c2[2] = c[2] * f;
10976                         c2[3] = c[3];
10977                 }
10978         }
10979         else
10980         {
10981                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10982                 {
10983                         f = RSurf_FogVertex(v);
10984                         c2[0] = f;
10985                         c2[1] = f;
10986                         c2[2] = f;
10987                         c2[3] = 1;
10988                 }
10989         }
10990         rsurface.passcolor4f = rsurface.array_passcolor4f;
10991         rsurface.passcolor4f_vertexbuffer = 0;
10992         rsurface.passcolor4f_bufferoffset = 0;
10993 }
10994
10995 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10996 {
10997         int i;
10998         float f;
10999         const float *v;
11000         const float *c;
11001         float *c2;
11002         if (!rsurface.passcolor4f)
11003                 return;
11004         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)
11005         {
11006                 f = RSurf_FogVertex(v);
11007                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
11008                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
11009                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
11010                 c2[3] = c[3];
11011         }
11012         rsurface.passcolor4f = rsurface.array_passcolor4f;
11013         rsurface.passcolor4f_vertexbuffer = 0;
11014         rsurface.passcolor4f_bufferoffset = 0;
11015 }
11016
11017 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
11018 {
11019         int i;
11020         const float *c;
11021         float *c2;
11022         if (!rsurface.passcolor4f)
11023                 return;
11024         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11025         {
11026                 c2[0] = c[0] * r;
11027                 c2[1] = c[1] * g;
11028                 c2[2] = c[2] * b;
11029                 c2[3] = c[3] * a;
11030         }
11031         rsurface.passcolor4f = rsurface.array_passcolor4f;
11032         rsurface.passcolor4f_vertexbuffer = 0;
11033         rsurface.passcolor4f_bufferoffset = 0;
11034 }
11035
11036 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
11037 {
11038         int i;
11039         const float *c;
11040         float *c2;
11041         if (!rsurface.passcolor4f)
11042                 return;
11043         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11044         {
11045                 c2[0] = c[0] + r_refdef.scene.ambient;
11046                 c2[1] = c[1] + r_refdef.scene.ambient;
11047                 c2[2] = c[2] + r_refdef.scene.ambient;
11048                 c2[3] = c[3];
11049         }
11050         rsurface.passcolor4f = rsurface.array_passcolor4f;
11051         rsurface.passcolor4f_vertexbuffer = 0;
11052         rsurface.passcolor4f_bufferoffset = 0;
11053 }
11054
11055 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11056 {
11057         // TODO: optimize
11058         rsurface.passcolor4f = NULL;
11059         rsurface.passcolor4f_vertexbuffer = 0;
11060         rsurface.passcolor4f_bufferoffset = 0;
11061         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11062         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11063         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11064         GL_Color(r, g, b, a);
11065         RSurf_BindLightmapForBatch();
11066         RSurf_DrawBatch();
11067 }
11068
11069 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11070 {
11071         // TODO: optimize applyfog && applycolor case
11072         // just apply fog if necessary, and tint the fog color array if necessary
11073         rsurface.passcolor4f = NULL;
11074         rsurface.passcolor4f_vertexbuffer = 0;
11075         rsurface.passcolor4f_bufferoffset = 0;
11076         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11077         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11078         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11079         GL_Color(r, g, b, a);
11080         RSurf_DrawBatch();
11081 }
11082
11083 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11084 {
11085         // TODO: optimize
11086         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11087         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11088         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11089         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11090         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11091         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11092         GL_Color(r, g, b, a);
11093         RSurf_DrawBatch();
11094 }
11095
11096 static void RSurf_DrawBatch_GL11_ClampColor(void)
11097 {
11098         int i;
11099         const float *c1;
11100         float *c2;
11101         if (!rsurface.passcolor4f)
11102                 return;
11103         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
11104         {
11105                 c2[0] = bound(0.0f, c1[0], 1.0f);
11106                 c2[1] = bound(0.0f, c1[1], 1.0f);
11107                 c2[2] = bound(0.0f, c1[2], 1.0f);
11108                 c2[3] = bound(0.0f, c1[3], 1.0f);
11109         }
11110 }
11111
11112 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
11113 {
11114         int i;
11115         float f;
11116         float alpha;
11117         const float *v;
11118         const float *n;
11119         float *c;
11120         vec3_t ambientcolor;
11121         vec3_t diffusecolor;
11122         vec3_t lightdir;
11123         // TODO: optimize
11124         // model lighting
11125         VectorCopy(rsurface.modellight_lightdir, lightdir);
11126         f = 0.5f * r_refdef.lightmapintensity;
11127         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
11128         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
11129         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
11130         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
11131         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
11132         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
11133         alpha = *a;
11134         if (VectorLength2(diffusecolor) > 0)
11135         {
11136                 // q3-style directional shading
11137                 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)
11138                 {
11139                         if ((f = DotProduct(n, lightdir)) > 0)
11140                                 VectorMA(ambientcolor, f, diffusecolor, c);
11141                         else
11142                                 VectorCopy(ambientcolor, c);
11143                         c[3] = alpha;
11144                 }
11145                 *r = 1;
11146                 *g = 1;
11147                 *b = 1;
11148                 *a = 1;
11149                 rsurface.passcolor4f = rsurface.array_passcolor4f;
11150                 rsurface.passcolor4f_vertexbuffer = 0;
11151                 rsurface.passcolor4f_bufferoffset = 0;
11152                 *applycolor = false;
11153         }
11154         else
11155         {
11156                 *r = ambientcolor[0];
11157                 *g = ambientcolor[1];
11158                 *b = ambientcolor[2];
11159                 rsurface.passcolor4f = NULL;
11160                 rsurface.passcolor4f_vertexbuffer = 0;
11161                 rsurface.passcolor4f_bufferoffset = 0;
11162         }
11163 }
11164
11165 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11166 {
11167         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
11168         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11169         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11170         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11171         GL_Color(r, g, b, a);
11172         RSurf_DrawBatch();
11173 }
11174
11175 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
11176 {
11177         int i;
11178         float f;
11179         const float *v;
11180         float *c;
11181         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
11182         {
11183                 f = 1 - RSurf_FogVertex(v);
11184                 c[0] = r;
11185                 c[1] = g;
11186                 c[2] = b;
11187                 c[3] = f * a;
11188         }
11189 }
11190
11191 void RSurf_SetupDepthAndCulling(void)
11192 {
11193         // submodels are biased to avoid z-fighting with world surfaces that they
11194         // may be exactly overlapping (avoids z-fighting artifacts on certain
11195         // doors and things in Quake maps)
11196         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
11197         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
11198         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
11199         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11200 }
11201
11202 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11203 {
11204         // transparent sky would be ridiculous
11205         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11206                 return;
11207         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11208         skyrenderlater = true;
11209         RSurf_SetupDepthAndCulling();
11210         GL_DepthMask(true);
11211         // LordHavoc: HalfLife maps have freaky skypolys so don't use
11212         // skymasking on them, and Quake3 never did sky masking (unlike
11213         // software Quake and software Quake2), so disable the sky masking
11214         // in Quake3 maps as it causes problems with q3map2 sky tricks,
11215         // and skymasking also looks very bad when noclipping outside the
11216         // level, so don't use it then either.
11217         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
11218         {
11219                 R_Mesh_ResetTextureState();
11220                 if (skyrendermasked)
11221                 {
11222                         R_SetupShader_DepthOrShadow();
11223                         // depth-only (masking)
11224                         GL_ColorMask(0,0,0,0);
11225                         // just to make sure that braindead drivers don't draw
11226                         // anything despite that colormask...
11227                         GL_BlendFunc(GL_ZERO, GL_ONE);
11228                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
11229                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
11230                 }
11231                 else
11232                 {
11233                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11234                         // fog sky
11235                         GL_BlendFunc(GL_ONE, GL_ZERO);
11236                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
11237                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
11238                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11239                 }
11240                 RSurf_DrawBatch();
11241                 if (skyrendermasked)
11242                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11243         }
11244         R_Mesh_ResetTextureState();
11245         GL_Color(1, 1, 1, 1);
11246 }
11247
11248 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
11249 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
11250 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11251 {
11252         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
11253                 return;
11254         if (prepass)
11255         {
11256                 // render screenspace normalmap to texture
11257                 GL_DepthMask(true);
11258                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist);
11259                 RSurf_DrawBatch();
11260         }
11261         else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
11262         {
11263                 // render water or distortion background, then blend surface on top
11264                 GL_DepthMask(true);
11265                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, texturenumsurfaces, texturesurfacelist);
11266                 RSurf_BindReflectionForBatch();
11267                 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
11268                         RSurf_BindLightmapForBatch();
11269                 RSurf_DrawBatch();
11270                 GL_DepthMask(false);
11271                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist);
11272                 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
11273                         RSurf_BindLightmapForBatch();
11274                 RSurf_DrawBatch();
11275         }
11276         else
11277         {
11278                 // render surface normally
11279                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
11280                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist);
11281                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
11282                         RSurf_BindReflectionForBatch();
11283                 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
11284                         RSurf_BindLightmapForBatch();
11285                 RSurf_DrawBatch();
11286         }
11287 }
11288
11289 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11290 {
11291         // OpenGL 1.3 path - anything not completely ancient
11292         qboolean applycolor;
11293         qboolean applyfog;
11294         int layerindex;
11295         const texturelayer_t *layer;
11296         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);
11297         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11298
11299         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
11300         {
11301                 vec4_t layercolor;
11302                 int layertexrgbscale;
11303                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11304                 {
11305                         if (layerindex == 0)
11306                                 GL_AlphaTest(true);
11307                         else
11308                         {
11309                                 GL_AlphaTest(false);
11310                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
11311                         }
11312                 }
11313                 GL_DepthMask(layer->depthmask && writedepth);
11314                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
11315                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
11316                 {
11317                         layertexrgbscale = 4;
11318                         VectorScale(layer->color, 0.25f, layercolor);
11319                 }
11320                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
11321                 {
11322                         layertexrgbscale = 2;
11323                         VectorScale(layer->color, 0.5f, layercolor);
11324                 }
11325                 else
11326                 {
11327                         layertexrgbscale = 1;
11328                         VectorScale(layer->color, 1.0f, layercolor);
11329                 }
11330                 layercolor[3] = layer->color[3];
11331                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
11332                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
11333                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
11334                 switch (layer->type)
11335                 {
11336                 case TEXTURELAYERTYPE_LITTEXTURE:
11337                         // single-pass lightmapped texture with 2x rgbscale
11338                         R_Mesh_TexBind(0, r_texture_white);
11339                         R_Mesh_TexMatrix(0, NULL);
11340                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11341                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
11342                         R_Mesh_TexBind(1, layer->texture);
11343                         R_Mesh_TexMatrix(1, &layer->texmatrix);
11344                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11345                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11346                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11347                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11348                         else if (rsurface.uselightmaptexture)
11349                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11350                         else
11351                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11352                         break;
11353                 case TEXTURELAYERTYPE_TEXTURE:
11354                         // singletexture unlit texture with transparency support
11355                         R_Mesh_TexBind(0, layer->texture);
11356                         R_Mesh_TexMatrix(0, &layer->texmatrix);
11357                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11358                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11359                         R_Mesh_TexBind(1, 0);
11360                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11361                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11362                         break;
11363                 case TEXTURELAYERTYPE_FOG:
11364                         // singletexture fogging
11365                         if (layer->texture)
11366                         {
11367                                 R_Mesh_TexBind(0, layer->texture);
11368                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11369                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11370                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11371                         }
11372                         else
11373                         {
11374                                 R_Mesh_TexBind(0, 0);
11375                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11376                         }
11377                         R_Mesh_TexBind(1, 0);
11378                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11379                         // generate a color array for the fog pass
11380                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
11381                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
11382                         RSurf_DrawBatch();
11383                         break;
11384                 default:
11385                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11386                 }
11387         }
11388         CHECKGLERROR
11389         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11390         {
11391                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
11392                 GL_AlphaTest(false);
11393         }
11394 }
11395
11396 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11397 {
11398         // OpenGL 1.1 - crusty old voodoo path
11399         qboolean applyfog;
11400         int layerindex;
11401         const texturelayer_t *layer;
11402         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);
11403         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11404
11405         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
11406         {
11407                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11408                 {
11409                         if (layerindex == 0)
11410                                 GL_AlphaTest(true);
11411                         else
11412                         {
11413                                 GL_AlphaTest(false);
11414                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
11415                         }
11416                 }
11417                 GL_DepthMask(layer->depthmask && writedepth);
11418                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
11419                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
11420                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
11421                 switch (layer->type)
11422                 {
11423                 case TEXTURELAYERTYPE_LITTEXTURE:
11424                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
11425                         {
11426                                 // two-pass lit texture with 2x rgbscale
11427                                 // first the lightmap pass
11428                                 R_Mesh_TexBind(0, r_texture_white);
11429                                 R_Mesh_TexMatrix(0, NULL);
11430                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11431                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
11432                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11433                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
11434                                 else if (rsurface.uselightmaptexture)
11435                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
11436                                 else
11437                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
11438                                 // then apply the texture to it
11439                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
11440                                 R_Mesh_TexBind(0, layer->texture);
11441                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11442                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11443                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11444                                 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);
11445                         }
11446                         else
11447                         {
11448                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
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                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11454                                         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);
11455                                 else
11456                                         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);
11457                         }
11458                         break;
11459                 case TEXTURELAYERTYPE_TEXTURE:
11460                         // singletexture unlit texture with transparency support
11461                         R_Mesh_TexBind(0, layer->texture);
11462                         R_Mesh_TexMatrix(0, &layer->texmatrix);
11463                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11464                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11465                         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);
11466                         break;
11467                 case TEXTURELAYERTYPE_FOG:
11468                         // singletexture fogging
11469                         if (layer->texture)
11470                         {
11471                                 R_Mesh_TexBind(0, layer->texture);
11472                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11473                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11474                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11475                         }
11476                         else
11477                         {
11478                                 R_Mesh_TexBind(0, 0);
11479                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11480                         }
11481                         // generate a color array for the fog pass
11482                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
11483                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
11484                         RSurf_DrawBatch();
11485                         break;
11486                 default:
11487                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11488                 }
11489         }
11490         CHECKGLERROR
11491         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11492         {
11493                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
11494                 GL_AlphaTest(false);
11495         }
11496 }
11497
11498 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11499 {
11500         int vi;
11501         int j;
11502         r_vertexgeneric_t *batchvertex;
11503         float c[4];
11504
11505         GL_AlphaTest(false);
11506         R_Mesh_ResetTextureState();
11507         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11508
11509         if(rsurface.texture && rsurface.texture->currentskinframe)
11510         {
11511                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11512                 c[3] *= rsurface.texture->currentalpha;
11513         }
11514         else
11515         {
11516                 c[0] = 1;
11517                 c[1] = 0;
11518                 c[2] = 1;
11519                 c[3] = 1;
11520         }
11521
11522         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11523         {
11524                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11525                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11526                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11527         }
11528
11529         // brighten it up (as texture value 127 means "unlit")
11530         c[0] *= 2 * r_refdef.view.colorscale;
11531         c[1] *= 2 * r_refdef.view.colorscale;
11532         c[2] *= 2 * r_refdef.view.colorscale;
11533
11534         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11535                 c[3] *= r_wateralpha.value;
11536
11537         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11538         {
11539                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11540                 GL_DepthMask(false);
11541         }
11542         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11543         {
11544                 GL_BlendFunc(GL_ONE, GL_ONE);
11545                 GL_DepthMask(false);
11546         }
11547         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11548         {
11549                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11550                 GL_DepthMask(false);
11551         }
11552         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11553         {
11554                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11555                 GL_DepthMask(false);
11556         }
11557         else
11558         {
11559                 GL_BlendFunc(GL_ONE, GL_ZERO);
11560                 GL_DepthMask(writedepth);
11561         }
11562
11563         if (r_showsurfaces.integer == 3)
11564         {
11565                 rsurface.passcolor4f = NULL;
11566
11567                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11568                 {
11569                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11570
11571                         rsurface.passcolor4f = NULL;
11572                         rsurface.passcolor4f_vertexbuffer = 0;
11573                         rsurface.passcolor4f_bufferoffset = 0;
11574                 }
11575                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11576                 {
11577                         qboolean applycolor = true;
11578                         float one = 1.0;
11579
11580                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11581
11582                         r_refdef.lightmapintensity = 1;
11583                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11584                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11585                 }
11586                 else
11587                 {
11588                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11589
11590                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11591                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11592                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11593                 }
11594
11595                 if(!rsurface.passcolor4f)
11596                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11597
11598                 RSurf_DrawBatch_GL11_ApplyAmbient();
11599                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11600                 if(r_refdef.fogenabled)
11601                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11602                 RSurf_DrawBatch_GL11_ClampColor();
11603
11604                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11605                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11606                 RSurf_DrawBatch();
11607         }
11608         else if (!r_refdef.view.showdebug)
11609         {
11610                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11611                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11612                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
11613                 {
11614                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11615                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
11616                 }
11617                 R_Mesh_PrepareVertices_Generic_Unlock();
11618                 RSurf_DrawBatch();
11619         }
11620         else if (r_showsurfaces.integer == 4)
11621         {
11622                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11623                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11624                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
11625                 {
11626                         unsigned char c = vi << 3;
11627                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11628                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
11629                 }
11630                 R_Mesh_PrepareVertices_Generic_Unlock();
11631                 RSurf_DrawBatch();
11632         }
11633         else if (r_showsurfaces.integer == 2)
11634         {
11635                 const int *e;
11636                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11637                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11638                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11639                 {
11640                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
11641                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11642                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11643                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11644                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
11645                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
11646                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
11647                 }
11648                 R_Mesh_PrepareVertices_Generic_Unlock();
11649                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11650         }
11651         else
11652         {
11653                 int texturesurfaceindex;
11654                 int k;
11655                 const msurface_t *surface;
11656                 unsigned char surfacecolor4ub[4];
11657                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11658                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11659                 vi = 0;
11660                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11661                 {
11662                         surface = texturesurfacelist[texturesurfaceindex];
11663                         k = (int)(((size_t)surface) / sizeof(msurface_t));
11664                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
11665                         for (j = 0;j < surface->num_vertices;j++)
11666                         {
11667                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11668                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
11669                                 vi++;
11670                         }
11671                 }
11672                 R_Mesh_PrepareVertices_Generic_Unlock();
11673                 RSurf_DrawBatch();
11674         }
11675 }
11676
11677 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11678 {
11679         CHECKGLERROR
11680         RSurf_SetupDepthAndCulling();
11681         if (r_showsurfaces.integer)
11682         {
11683                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11684                 return;
11685         }
11686         switch (vid.renderpath)
11687         {
11688         case RENDERPATH_GL20:
11689         case RENDERPATH_CGGL:
11690                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11691                 break;
11692         case RENDERPATH_GL13:
11693                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11694                 break;
11695         case RENDERPATH_GL11:
11696                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11697                 break;
11698         }
11699         CHECKGLERROR
11700 }
11701
11702 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11703 {
11704         CHECKGLERROR
11705         RSurf_SetupDepthAndCulling();
11706         if (r_showsurfaces.integer)
11707         {
11708                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11709                 return;
11710         }
11711         switch (vid.renderpath)
11712         {
11713         case RENDERPATH_GL20:
11714         case RENDERPATH_CGGL:
11715                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11716                 break;
11717         case RENDERPATH_GL13:
11718                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11719                 break;
11720         case RENDERPATH_GL11:
11721                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11722                 break;
11723         }
11724         CHECKGLERROR
11725 }
11726
11727 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11728 {
11729         int i, j;
11730         int texturenumsurfaces, endsurface;
11731         texture_t *texture;
11732         const msurface_t *surface;
11733 #define MAXBATCH_TRANSPARENTSURFACES 256
11734         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
11735
11736         // if the model is static it doesn't matter what value we give for
11737         // wantnormals and wanttangents, so this logic uses only rules applicable
11738         // to a model, knowing that they are meaningless otherwise
11739         if (ent == r_refdef.scene.worldentity)
11740                 RSurf_ActiveWorldEntity();
11741         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11742                 RSurf_ActiveModelEntity(ent, false, false, false);
11743         else
11744         {
11745                 switch (vid.renderpath)
11746                 {
11747                 case RENDERPATH_GL20:
11748                 case RENDERPATH_CGGL:
11749                         RSurf_ActiveModelEntity(ent, true, true, false);
11750                         break;
11751                 case RENDERPATH_GL13:
11752                 case RENDERPATH_GL11:
11753                         RSurf_ActiveModelEntity(ent, true, false, false);
11754                         break;
11755                 }
11756         }
11757
11758         if (r_transparentdepthmasking.integer)
11759         {
11760                 qboolean setup = false;
11761                 for (i = 0;i < numsurfaces;i = j)
11762                 {
11763                         j = i + 1;
11764                         surface = rsurface.modelsurfaces + surfacelist[i];
11765                         texture = surface->texture;
11766                         rsurface.texture = R_GetCurrentTexture(texture);
11767                         rsurface.lightmaptexture = NULL;
11768                         rsurface.deluxemaptexture = NULL;
11769                         rsurface.uselightmaptexture = false;
11770                         // scan ahead until we find a different texture
11771                         endsurface = min(i + 1024, numsurfaces);
11772                         texturenumsurfaces = 0;
11773                         texturesurfacelist[texturenumsurfaces++] = surface;
11774                         for (;j < endsurface;j++)
11775                         {
11776                                 surface = rsurface.modelsurfaces + surfacelist[j];
11777                                 if (texture != surface->texture)
11778                                         break;
11779                                 texturesurfacelist[texturenumsurfaces++] = surface;
11780                         }
11781                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11782                                 continue;
11783                         // render the range of surfaces as depth
11784                         if (!setup)
11785                         {
11786                                 setup = true;
11787                                 GL_ColorMask(0,0,0,0);
11788                                 GL_Color(1,1,1,1);
11789                                 GL_DepthTest(true);
11790                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11791                                 GL_DepthMask(true);
11792                                 GL_AlphaTest(false);
11793                                 R_Mesh_ResetTextureState();
11794                                 R_SetupShader_DepthOrShadow();
11795                         }
11796                         RSurf_SetupDepthAndCulling();
11797                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
11798                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
11799                         RSurf_DrawBatch();
11800                 }
11801                 if (setup)
11802                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11803         }
11804
11805         for (i = 0;i < numsurfaces;i = j)
11806         {
11807                 j = i + 1;
11808                 surface = rsurface.modelsurfaces + surfacelist[i];
11809                 texture = surface->texture;
11810                 rsurface.texture = R_GetCurrentTexture(texture);
11811                 rsurface.lightmaptexture = surface->lightmaptexture;
11812                 rsurface.deluxemaptexture = surface->deluxemaptexture;
11813                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11814                 // scan ahead until we find a different texture
11815                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
11816                 texturenumsurfaces = 0;
11817                 texturesurfacelist[texturenumsurfaces++] = surface;
11818                 for (;j < endsurface;j++)
11819                 {
11820                         surface = rsurface.modelsurfaces + surfacelist[j];
11821                         if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11822                                 break;
11823                         texturesurfacelist[texturenumsurfaces++] = surface;
11824                 }
11825                 // render the range of surfaces
11826                 if (ent == r_refdef.scene.worldentity)
11827                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11828                 else
11829                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11830         }
11831         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11832         GL_AlphaTest(false);
11833 }
11834
11835 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
11836 {
11837         // transparent surfaces get pushed off into the transparent queue
11838         int surfacelistindex;
11839         const msurface_t *surface;
11840         vec3_t tempcenter, center;
11841         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11842         {
11843                 surface = texturesurfacelist[surfacelistindex];
11844                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11845                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11846                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11847                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11848                 if (queueentity->transparent_offset) // transparent offset
11849                 {
11850                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
11851                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
11852                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
11853                 }
11854                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
11855         }
11856 }
11857
11858 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11859 {
11860         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11861                 return;
11862         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11863                 return;
11864         RSurf_SetupDepthAndCulling();
11865         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
11866         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
11867         RSurf_DrawBatch();
11868 }
11869
11870 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11871 {
11872         const entity_render_t *queueentity = r_refdef.scene.worldentity;
11873         CHECKGLERROR
11874         if (depthonly)
11875                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11876         else if (prepass)
11877         {
11878                 if (!rsurface.texture->currentnumlayers)
11879                         return;
11880                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11881                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11882                 else
11883                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11884         }
11885         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
11886                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11887         else if (!rsurface.texture->currentnumlayers)
11888                 return;
11889         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11890         {
11891                 // in the deferred case, transparent surfaces were queued during prepass
11892                 if (!r_shadow_usingdeferredprepass)
11893                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11894         }
11895         else
11896         {
11897                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11898                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11899         }
11900         CHECKGLERROR
11901 }
11902
11903 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11904 {
11905         int i, j;
11906         texture_t *texture;
11907         // break the surface list down into batches by texture and use of lightmapping
11908         for (i = 0;i < numsurfaces;i = j)
11909         {
11910                 j = i + 1;
11911                 // texture is the base texture pointer, rsurface.texture is the
11912                 // current frame/skin the texture is directing us to use (for example
11913                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11914                 // use skin 1 instead)
11915                 texture = surfacelist[i]->texture;
11916                 rsurface.texture = R_GetCurrentTexture(texture);
11917                 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11918                 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11919                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11920                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11921                 {
11922                         // if this texture is not the kind we want, skip ahead to the next one
11923                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11924                                 ;
11925                         continue;
11926                 }
11927                 // simply scan ahead until we find a different texture or lightmap state
11928                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11929                         ;
11930                 // render the range of surfaces
11931                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11932         }
11933 }
11934
11935 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
11936 {
11937         CHECKGLERROR
11938         if (depthonly)
11939                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11940         else if (prepass)
11941         {
11942                 if (!rsurface.texture->currentnumlayers)
11943                         return;
11944                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11945                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11946                 else
11947                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11948         }
11949         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
11950                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11951         else if (!rsurface.texture->currentnumlayers)
11952                 return;
11953         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11954         {
11955                 // in the deferred case, transparent surfaces were queued during prepass
11956                 if (!r_shadow_usingdeferredprepass)
11957                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11958         }
11959         else
11960         {
11961                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11962                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11963         }
11964         CHECKGLERROR
11965 }
11966
11967 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11968 {
11969         int i, j;
11970         texture_t *texture;
11971         // break the surface list down into batches by texture and use of lightmapping
11972         for (i = 0;i < numsurfaces;i = j)
11973         {
11974                 j = i + 1;
11975                 // texture is the base texture pointer, rsurface.texture is the
11976                 // current frame/skin the texture is directing us to use (for example
11977                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11978                 // use skin 1 instead)
11979                 texture = surfacelist[i]->texture;
11980                 rsurface.texture = R_GetCurrentTexture(texture);
11981                 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11982                 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11983                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11984                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11985                 {
11986                         // if this texture is not the kind we want, skip ahead to the next one
11987                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11988                                 ;
11989                         continue;
11990                 }
11991                 // simply scan ahead until we find a different texture or lightmap state
11992                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11993                         ;
11994                 // render the range of surfaces
11995                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
11996         }
11997 }
11998
11999 float locboxvertex3f[6*4*3] =
12000 {
12001         1,0,1, 1,0,0, 1,1,0, 1,1,1,
12002         0,1,1, 0,1,0, 0,0,0, 0,0,1,
12003         1,1,1, 1,1,0, 0,1,0, 0,1,1,
12004         0,0,1, 0,0,0, 1,0,0, 1,0,1,
12005         0,0,1, 1,0,1, 1,1,1, 0,1,1,
12006         1,0,0, 0,0,0, 0,1,0, 1,1,0
12007 };
12008
12009 unsigned short locboxelements[6*2*3] =
12010 {
12011          0, 1, 2, 0, 2, 3,
12012          4, 5, 6, 4, 6, 7,
12013          8, 9,10, 8,10,11,
12014         12,13,14, 12,14,15,
12015         16,17,18, 16,18,19,
12016         20,21,22, 20,22,23
12017 };
12018
12019 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12020 {
12021         int i, j;
12022         cl_locnode_t *loc = (cl_locnode_t *)ent;
12023         vec3_t mins, size;
12024         float vertex3f[6*4*3];
12025         CHECKGLERROR
12026         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12027         GL_DepthMask(false);
12028         GL_DepthRange(0, 1);
12029         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12030         GL_DepthTest(true);
12031         GL_CullFace(GL_NONE);
12032         R_EntityMatrix(&identitymatrix);
12033
12034         R_Mesh_ResetTextureState();
12035
12036         i = surfacelist[0];
12037         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12038                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12039                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12040                         surfacelist[0] < 0 ? 0.5f : 0.125f);
12041
12042         if (VectorCompare(loc->mins, loc->maxs))
12043         {
12044                 VectorSet(size, 2, 2, 2);
12045                 VectorMA(loc->mins, -0.5f, size, mins);
12046         }
12047         else
12048         {
12049                 VectorCopy(loc->mins, mins);
12050                 VectorSubtract(loc->maxs, loc->mins, size);
12051         }
12052
12053         for (i = 0;i < 6*4*3;)
12054                 for (j = 0;j < 3;j++, i++)
12055                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
12056
12057         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
12058         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12059         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
12060 }
12061
12062 void R_DrawLocs(void)
12063 {
12064         int index;
12065         cl_locnode_t *loc, *nearestloc;
12066         vec3_t center;
12067         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
12068         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
12069         {
12070                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
12071                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
12072         }
12073 }
12074
12075 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
12076 {
12077         if (decalsystem->decals)
12078                 Mem_Free(decalsystem->decals);
12079         memset(decalsystem, 0, sizeof(*decalsystem));
12080 }
12081
12082 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)
12083 {
12084         tridecal_t *decal;
12085         tridecal_t *decals;
12086         int i;
12087
12088         // expand or initialize the system
12089         if (decalsystem->maxdecals <= decalsystem->numdecals)
12090         {
12091                 decalsystem_t old = *decalsystem;
12092                 qboolean useshortelements;
12093                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
12094                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
12095                 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)));
12096                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
12097                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
12098                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
12099                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
12100                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
12101                 if (decalsystem->numdecals)
12102                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
12103                 if (old.decals)
12104                         Mem_Free(old.decals);
12105                 for (i = 0;i < decalsystem->maxdecals*3;i++)
12106                         decalsystem->element3i[i] = i;
12107                 if (useshortelements)
12108                         for (i = 0;i < decalsystem->maxdecals*3;i++)
12109                                 decalsystem->element3s[i] = i;
12110         }
12111
12112         // grab a decal and search for another free slot for the next one
12113         decals = decalsystem->decals;
12114         decal = decalsystem->decals + (i = decalsystem->freedecal++);
12115         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
12116                 ;
12117         decalsystem->freedecal = i;
12118         if (decalsystem->numdecals <= i)
12119                 decalsystem->numdecals = i + 1;
12120
12121         // initialize the decal
12122         decal->lived = 0;
12123         decal->triangleindex = triangleindex;
12124         decal->surfaceindex = surfaceindex;
12125         decal->decalsequence = decalsequence;
12126         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
12127         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
12128         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
12129         decal->color4ub[0][3] = 255;
12130         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
12131         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
12132         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
12133         decal->color4ub[1][3] = 255;
12134         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
12135         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
12136         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
12137         decal->color4ub[2][3] = 255;
12138         decal->vertex3f[0][0] = v0[0];
12139         decal->vertex3f[0][1] = v0[1];
12140         decal->vertex3f[0][2] = v0[2];
12141         decal->vertex3f[1][0] = v1[0];
12142         decal->vertex3f[1][1] = v1[1];
12143         decal->vertex3f[1][2] = v1[2];
12144         decal->vertex3f[2][0] = v2[0];
12145         decal->vertex3f[2][1] = v2[1];
12146         decal->vertex3f[2][2] = v2[2];
12147         decal->texcoord2f[0][0] = t0[0];
12148         decal->texcoord2f[0][1] = t0[1];
12149         decal->texcoord2f[1][0] = t1[0];
12150         decal->texcoord2f[1][1] = t1[1];
12151         decal->texcoord2f[2][0] = t2[0];
12152         decal->texcoord2f[2][1] = t2[1];
12153 }
12154
12155 extern cvar_t cl_decals_bias;
12156 extern cvar_t cl_decals_models;
12157 extern cvar_t cl_decals_newsystem_intensitymultiplier;
12158 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)
12159 {
12160         matrix4x4_t projection;
12161         decalsystem_t *decalsystem;
12162         qboolean dynamic;
12163         dp_model_t *model;
12164         const float *vertex3f;
12165         const msurface_t *surface;
12166         const msurface_t *surfaces;
12167         const int *surfacelist;
12168         const texture_t *texture;
12169         int numtriangles;
12170         int numsurfacelist;
12171         int surfacelistindex;
12172         int surfaceindex;
12173         int triangleindex;
12174         int cornerindex;
12175         int index;
12176         int numpoints;
12177         const int *e;
12178         float localorigin[3];
12179         float localnormal[3];
12180         float localmins[3];
12181         float localmaxs[3];
12182         float localsize;
12183         float v[9][3];
12184         float tc[9][2];
12185         float c[9][4];
12186         //float normal[3];
12187         float planes[6][4];
12188         float f;
12189         float points[2][9][3];
12190         float angles[3];
12191         float temp[3];
12192
12193         decalsystem = &ent->decalsystem;
12194         model = ent->model;
12195         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
12196         {
12197                 R_DecalSystem_Reset(&ent->decalsystem);
12198                 return;
12199         }
12200
12201         if (!model->brush.data_nodes && !cl_decals_models.integer)
12202         {
12203                 if (decalsystem->model)
12204                         R_DecalSystem_Reset(decalsystem);
12205                 return;
12206         }
12207
12208         if (decalsystem->model != model)
12209                 R_DecalSystem_Reset(decalsystem);
12210         decalsystem->model = model;
12211
12212         RSurf_ActiveModelEntity(ent, false, false, false);
12213
12214         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
12215         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
12216         VectorNormalize(localnormal);
12217         localsize = worldsize*rsurface.inversematrixscale;
12218         localmins[0] = localorigin[0] - localsize;
12219         localmins[1] = localorigin[1] - localsize;
12220         localmins[2] = localorigin[2] - localsize;
12221         localmaxs[0] = localorigin[0] + localsize;
12222         localmaxs[1] = localorigin[1] + localsize;
12223         localmaxs[2] = localorigin[2] + localsize;
12224
12225         //VectorCopy(localnormal, planes[4]);
12226         //VectorVectors(planes[4], planes[2], planes[0]);
12227         AnglesFromVectors(angles, localnormal, NULL, false);
12228         AngleVectors(angles, planes[0], planes[2], planes[4]);
12229         VectorNegate(planes[0], planes[1]);
12230         VectorNegate(planes[2], planes[3]);
12231         VectorNegate(planes[4], planes[5]);
12232         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
12233         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
12234         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
12235         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
12236         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
12237         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
12238
12239 #if 1
12240 // works
12241 {
12242         matrix4x4_t forwardprojection;
12243         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
12244         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
12245 }
12246 #else
12247 // broken
12248 {
12249         float projectionvector[4][3];
12250         VectorScale(planes[0], ilocalsize, projectionvector[0]);
12251         VectorScale(planes[2], ilocalsize, projectionvector[1]);
12252         VectorScale(planes[4], ilocalsize, projectionvector[2]);
12253         projectionvector[0][0] = planes[0][0] * ilocalsize;
12254         projectionvector[0][1] = planes[1][0] * ilocalsize;
12255         projectionvector[0][2] = planes[2][0] * ilocalsize;
12256         projectionvector[1][0] = planes[0][1] * ilocalsize;
12257         projectionvector[1][1] = planes[1][1] * ilocalsize;
12258         projectionvector[1][2] = planes[2][1] * ilocalsize;
12259         projectionvector[2][0] = planes[0][2] * ilocalsize;
12260         projectionvector[2][1] = planes[1][2] * ilocalsize;
12261         projectionvector[2][2] = planes[2][2] * ilocalsize;
12262         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
12263         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
12264         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
12265         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
12266 }
12267 #endif
12268
12269         dynamic = model->surfmesh.isanimated;
12270         vertex3f = rsurface.modelvertex3f;
12271         numsurfacelist = model->nummodelsurfaces;
12272         surfacelist = model->sortedmodelsurfaces;
12273         surfaces = model->data_surfaces;
12274         for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
12275         {
12276                 surfaceindex = surfacelist[surfacelistindex];
12277                 surface = surfaces + surfaceindex;
12278                 // check cull box first because it rejects more than any other check
12279                 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
12280                         continue;
12281                 // skip transparent surfaces
12282                 texture = surface->texture;
12283                 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12284                         continue;
12285                 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12286                         continue;
12287                 numtriangles = surface->num_triangles;
12288                 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
12289                 {
12290                         for (cornerindex = 0;cornerindex < 3;cornerindex++)
12291                         {
12292                                 index = 3*e[cornerindex];
12293                                 VectorCopy(vertex3f + index, v[cornerindex]);
12294                         }
12295                         // cull backfaces
12296                         //TriangleNormal(v[0], v[1], v[2], normal);
12297                         //if (DotProduct(normal, localnormal) < 0.0f)
12298                         //      continue;
12299                         // clip by each of the box planes formed from the projection matrix
12300                         // if anything survives, we emit the decal
12301                         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]);
12302                         if (numpoints < 3)
12303                                 continue;
12304                         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]);
12305                         if (numpoints < 3)
12306                                 continue;
12307                         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]);
12308                         if (numpoints < 3)
12309                                 continue;
12310                         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]);
12311                         if (numpoints < 3)
12312                                 continue;
12313                         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]);
12314                         if (numpoints < 3)
12315                                 continue;
12316                         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]);
12317                         if (numpoints < 3)
12318                                 continue;
12319                         // some part of the triangle survived, so we have to accept it...
12320                         if (dynamic)
12321                         {
12322                                 // dynamic always uses the original triangle
12323                                 numpoints = 3;
12324                                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
12325                                 {
12326                                         index = 3*e[cornerindex];
12327                                         VectorCopy(vertex3f + index, v[cornerindex]);
12328                                 }
12329                         }
12330                         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
12331                         {
12332                                 // convert vertex positions to texcoords
12333                                 Matrix4x4_Transform(&projection, v[cornerindex], temp);
12334                                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
12335                                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
12336                                 // calculate distance fade from the projection origin
12337                                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
12338                                 f = bound(0.0f, f, 1.0f);
12339                                 c[cornerindex][0] = r * f;
12340                                 c[cornerindex][1] = g * f;
12341                                 c[cornerindex][2] = b * f;
12342                                 c[cornerindex][3] = 1.0f;
12343                                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
12344                         }
12345                         if (dynamic)
12346                                 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);
12347                         else
12348                                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
12349                                         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);
12350                 }
12351         }
12352 }
12353
12354 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
12355 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)
12356 {
12357         int renderentityindex;
12358         float worldmins[3];
12359         float worldmaxs[3];
12360         entity_render_t *ent;
12361
12362         if (!cl_decals_newsystem.integer)
12363                 return;
12364
12365         worldmins[0] = worldorigin[0] - worldsize;
12366         worldmins[1] = worldorigin[1] - worldsize;
12367         worldmins[2] = worldorigin[2] - worldsize;
12368         worldmaxs[0] = worldorigin[0] + worldsize;
12369         worldmaxs[1] = worldorigin[1] + worldsize;
12370         worldmaxs[2] = worldorigin[2] + worldsize;
12371
12372         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12373
12374         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
12375         {
12376                 ent = r_refdef.scene.entities[renderentityindex];
12377                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
12378                         continue;
12379
12380                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12381         }
12382 }
12383
12384 typedef struct r_decalsystem_splatqueue_s
12385 {
12386         vec3_t worldorigin;
12387         vec3_t worldnormal;
12388         float color[4];
12389         float tcrange[4];
12390         float worldsize;
12391         int decalsequence;
12392 }
12393 r_decalsystem_splatqueue_t;
12394
12395 int r_decalsystem_numqueued = 0;
12396 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12397
12398 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)
12399 {
12400         r_decalsystem_splatqueue_t *queue;
12401
12402         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12403                 return;
12404
12405         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12406         VectorCopy(worldorigin, queue->worldorigin);
12407         VectorCopy(worldnormal, queue->worldnormal);
12408         Vector4Set(queue->color, r, g, b, a);
12409         Vector4Set(queue->tcrange, s1, t1, s2, t2);
12410         queue->worldsize = worldsize;
12411         queue->decalsequence = cl.decalsequence++;
12412 }
12413
12414 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12415 {
12416         int i;
12417         r_decalsystem_splatqueue_t *queue;
12418
12419         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12420                 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);
12421         r_decalsystem_numqueued = 0;
12422 }
12423
12424 extern cvar_t cl_decals_max;
12425 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12426 {
12427         int i;
12428         decalsystem_t *decalsystem = &ent->decalsystem;
12429         int numdecals;
12430         int killsequence;
12431         tridecal_t *decal;
12432         float frametime;
12433         float lifetime;
12434
12435         if (!decalsystem->numdecals)
12436                 return;
12437
12438         if (r_showsurfaces.integer)
12439                 return;
12440
12441         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12442         {
12443                 R_DecalSystem_Reset(decalsystem);
12444                 return;
12445         }
12446
12447         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
12448         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12449
12450         if (decalsystem->lastupdatetime)
12451                 frametime = (cl.time - decalsystem->lastupdatetime);
12452         else
12453                 frametime = 0;
12454         decalsystem->lastupdatetime = cl.time;
12455         decal = decalsystem->decals;
12456         numdecals = decalsystem->numdecals;
12457
12458         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12459         {
12460                 if (decal->color4ub[0][3])
12461                 {
12462                         decal->lived += frametime;
12463                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
12464                         {
12465                                 memset(decal, 0, sizeof(*decal));
12466                                 if (decalsystem->freedecal > i)
12467                                         decalsystem->freedecal = i;
12468                         }
12469                 }
12470         }
12471         decal = decalsystem->decals;
12472         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
12473                 numdecals--;
12474
12475         // collapse the array by shuffling the tail decals into the gaps
12476         for (;;)
12477         {
12478                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
12479                         decalsystem->freedecal++;
12480                 if (decalsystem->freedecal == numdecals)
12481                         break;
12482                 decal[decalsystem->freedecal] = decal[--numdecals];
12483         }
12484
12485         decalsystem->numdecals = numdecals;
12486
12487         if (numdecals <= 0)
12488         {
12489                 // if there are no decals left, reset decalsystem
12490                 R_DecalSystem_Reset(decalsystem);
12491         }
12492 }
12493
12494 extern skinframe_t *decalskinframe;
12495 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12496 {
12497         int i;
12498         decalsystem_t *decalsystem = &ent->decalsystem;
12499         int numdecals;
12500         tridecal_t *decal;
12501         float faderate;
12502         float alpha;
12503         float *v3f;
12504         float *c4f;
12505         float *t2f;
12506         const int *e;
12507         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12508         int numtris = 0;
12509
12510         numdecals = decalsystem->numdecals;
12511         if (!numdecals)
12512                 return;
12513
12514         if (r_showsurfaces.integer)
12515                 return;
12516
12517         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12518         {
12519                 R_DecalSystem_Reset(decalsystem);
12520                 return;
12521         }
12522
12523         // if the model is static it doesn't matter what value we give for
12524         // wantnormals and wanttangents, so this logic uses only rules applicable
12525         // to a model, knowing that they are meaningless otherwise
12526         if (ent == r_refdef.scene.worldentity)
12527                 RSurf_ActiveWorldEntity();
12528         else
12529                 RSurf_ActiveModelEntity(ent, false, false, false);
12530
12531         decalsystem->lastupdatetime = cl.time;
12532         decal = decalsystem->decals;
12533
12534         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12535
12536         // update vertex positions for animated models
12537         v3f = decalsystem->vertex3f;
12538         c4f = decalsystem->color4f;
12539         t2f = decalsystem->texcoord2f;
12540         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12541         {
12542                 if (!decal->color4ub[0][3])
12543                         continue;
12544
12545                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12546                         continue;
12547
12548                 // update color values for fading decals
12549                 if (decal->lived >= cl_decals_time.value)
12550                 {
12551                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12552                         alpha *= (1.0f/255.0f);
12553                 }
12554                 else
12555                         alpha = 1.0f/255.0f;
12556
12557                 c4f[ 0] = decal->color4ub[0][0] * alpha;
12558                 c4f[ 1] = decal->color4ub[0][1] * alpha;
12559                 c4f[ 2] = decal->color4ub[0][2] * alpha;
12560                 c4f[ 3] = 1;
12561                 c4f[ 4] = decal->color4ub[1][0] * alpha;
12562                 c4f[ 5] = decal->color4ub[1][1] * alpha;
12563                 c4f[ 6] = decal->color4ub[1][2] * alpha;
12564                 c4f[ 7] = 1;
12565                 c4f[ 8] = decal->color4ub[2][0] * alpha;
12566                 c4f[ 9] = decal->color4ub[2][1] * alpha;
12567                 c4f[10] = decal->color4ub[2][2] * alpha;
12568                 c4f[11] = 1;
12569
12570                 t2f[0] = decal->texcoord2f[0][0];
12571                 t2f[1] = decal->texcoord2f[0][1];
12572                 t2f[2] = decal->texcoord2f[1][0];
12573                 t2f[3] = decal->texcoord2f[1][1];
12574                 t2f[4] = decal->texcoord2f[2][0];
12575                 t2f[5] = decal->texcoord2f[2][1];
12576
12577                 // update vertex positions for animated models
12578                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12579                 {
12580                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12581                         VectorCopy(rsurface.modelvertexposition[e[0]].vertex3f, v3f);
12582                         VectorCopy(rsurface.modelvertexposition[e[1]].vertex3f, v3f + 3);
12583                         VectorCopy(rsurface.modelvertexposition[e[2]].vertex3f, v3f + 6);
12584                 }
12585                 else
12586                 {
12587                         VectorCopy(decal->vertex3f[0], v3f);
12588                         VectorCopy(decal->vertex3f[1], v3f + 3);
12589                         VectorCopy(decal->vertex3f[2], v3f + 6);
12590                 }
12591
12592                 if (r_refdef.fogenabled)
12593                 {
12594                         alpha = RSurf_FogVertex(v3f);
12595                         VectorScale(c4f, alpha, c4f);
12596                         alpha = RSurf_FogVertex(v3f + 3);
12597                         VectorScale(c4f + 4, alpha, c4f + 4);
12598                         alpha = RSurf_FogVertex(v3f + 6);
12599                         VectorScale(c4f + 8, alpha, c4f + 8);
12600                 }
12601
12602                 v3f += 9;
12603                 c4f += 12;
12604                 t2f += 6;
12605                 numtris++;
12606         }
12607
12608         if (numtris > 0)
12609         {
12610                 r_refdef.stats.drawndecals += numtris;
12611
12612                 // now render the decals all at once
12613                 // (this assumes they all use one particle font texture!)
12614                 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);
12615                 R_Mesh_ResetTextureState();
12616                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12617                 GL_DepthMask(false);
12618                 GL_DepthRange(0, 1);
12619                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12620                 GL_DepthTest(true);
12621                 GL_CullFace(GL_NONE);
12622                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12623                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
12624                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12625         }
12626 }
12627
12628 static void R_DrawModelDecals(void)
12629 {
12630         int i, numdecals;
12631
12632         // fade faster when there are too many decals
12633         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12634         for (i = 0;i < r_refdef.scene.numentities;i++)
12635                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12636
12637         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12638         for (i = 0;i < r_refdef.scene.numentities;i++)
12639                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12640                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12641
12642         R_DecalSystem_ApplySplatEntitiesQueue();
12643
12644         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12645         for (i = 0;i < r_refdef.scene.numentities;i++)
12646                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12647
12648         r_refdef.stats.totaldecals += numdecals;
12649
12650         if (r_showsurfaces.integer)
12651                 return;
12652
12653         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12654
12655         for (i = 0;i < r_refdef.scene.numentities;i++)
12656         {
12657                 if (!r_refdef.viewcache.entityvisible[i])
12658                         continue;
12659                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12660                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12661         }
12662 }
12663
12664 extern cvar_t mod_collision_bih;
12665 void R_DrawDebugModel(void)
12666 {
12667         entity_render_t *ent = rsurface.entity;
12668         int i, j, k, l, flagsmask;
12669         const msurface_t *surface;
12670         dp_model_t *model = ent->model;
12671         vec3_t v;
12672
12673         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12674
12675         R_Mesh_ResetTextureState();
12676         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12677         GL_DepthRange(0, 1);
12678         GL_DepthTest(!r_showdisabledepthtest.integer);
12679         GL_DepthMask(false);
12680         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12681
12682         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12683         {
12684                 int triangleindex;
12685                 int bihleafindex;
12686                 qboolean cullbox = ent == r_refdef.scene.worldentity;
12687                 const q3mbrush_t *brush;
12688                 const bih_t *bih = &model->collision_bih;
12689                 const bih_leaf_t *bihleaf;
12690                 float vertex3f[3][3];
12691                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12692                 cullbox = false;
12693                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12694                 {
12695                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12696                                 continue;
12697                         switch (bihleaf->type)
12698                         {
12699                         case BIH_BRUSH:
12700                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12701                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12702                                 {
12703                                         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);
12704                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12705                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12706                                 }
12707                                 break;
12708                         case BIH_COLLISIONTRIANGLE:
12709                                 triangleindex = bihleaf->itemindex;
12710                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12711                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12712                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12713                                 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);
12714                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12715                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12716                                 break;
12717                         case BIH_RENDERTRIANGLE:
12718                                 triangleindex = bihleaf->itemindex;
12719                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12720                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12721                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[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                         }
12727                 }
12728         }
12729
12730         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12731
12732         if (r_showtris.integer || r_shownormals.integer)
12733         {
12734                 if (r_showdisabledepthtest.integer)
12735                 {
12736                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12737                         GL_DepthMask(false);
12738                 }
12739                 else
12740                 {
12741                         GL_BlendFunc(GL_ONE, GL_ZERO);
12742                         GL_DepthMask(true);
12743                 }
12744                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12745                 {
12746                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12747                                 continue;
12748                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12749                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12750                         {
12751                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12752                                 if (r_showtris.value > 0)
12753                                 {
12754                                         if (!rsurface.texture->currentlayers->depthmask)
12755                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12756                                         else if (ent == r_refdef.scene.worldentity)
12757                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12758                                         else
12759                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12760                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12761                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
12762                                         RSurf_DrawBatch();
12763                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
12764                                         CHECKGLERROR
12765                                 }
12766                                 if (r_shownormals.value < 0)
12767                                 {
12768                                         qglBegin(GL_LINES);
12769                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12770                                         {
12771                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12772                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12773                                                 qglVertex3f(v[0], v[1], v[2]);
12774                                                 VectorMA(v, -r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12775                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12776                                                 qglVertex3f(v[0], v[1], v[2]);
12777                                         }
12778                                         qglEnd();
12779                                         CHECKGLERROR
12780                                 }
12781                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12782                                 {
12783                                         qglBegin(GL_LINES);
12784                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12785                                         {
12786                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12787                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12788                                                 qglVertex3f(v[0], v[1], v[2]);
12789                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12790                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12791                                                 qglVertex3f(v[0], v[1], v[2]);
12792                                         }
12793                                         qglEnd();
12794                                         CHECKGLERROR
12795                                         qglBegin(GL_LINES);
12796                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12797                                         {
12798                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12799                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12800                                                 qglVertex3f(v[0], v[1], v[2]);
12801                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12802                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12803                                                 qglVertex3f(v[0], v[1], v[2]);
12804                                         }
12805                                         qglEnd();
12806                                         CHECKGLERROR
12807                                         qglBegin(GL_LINES);
12808                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12809                                         {
12810                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12811                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12812                                                 qglVertex3f(v[0], v[1], v[2]);
12813                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12814                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12815                                                 qglVertex3f(v[0], v[1], v[2]);
12816                                         }
12817                                         qglEnd();
12818                                         CHECKGLERROR
12819                                 }
12820                         }
12821                 }
12822                 rsurface.texture = NULL;
12823         }
12824 }
12825
12826 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
12827 int r_maxsurfacelist = 0;
12828 const msurface_t **r_surfacelist = NULL;
12829 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12830 {
12831         int i, j, endj, flagsmask;
12832         dp_model_t *model = r_refdef.scene.worldmodel;
12833         msurface_t *surfaces;
12834         unsigned char *update;
12835         int numsurfacelist = 0;
12836         if (model == NULL)
12837                 return;
12838
12839         if (r_maxsurfacelist < model->num_surfaces)
12840         {
12841                 r_maxsurfacelist = model->num_surfaces;
12842                 if (r_surfacelist)
12843                         Mem_Free((msurface_t**)r_surfacelist);
12844                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12845         }
12846
12847         RSurf_ActiveWorldEntity();
12848
12849         surfaces = model->data_surfaces;
12850         update = model->brushq1.lightmapupdateflags;
12851
12852         // update light styles on this submodel
12853         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12854         {
12855                 model_brush_lightstyleinfo_t *style;
12856                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12857                 {
12858                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12859                         {
12860                                 int *list = style->surfacelist;
12861                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12862                                 for (j = 0;j < style->numsurfaces;j++)
12863                                         update[list[j]] = true;
12864                         }
12865                 }
12866         }
12867
12868         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12869
12870         if (debug)
12871         {
12872                 R_DrawDebugModel();
12873                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12874                 return;
12875         }
12876
12877         rsurface.lightmaptexture = NULL;
12878         rsurface.deluxemaptexture = NULL;
12879         rsurface.uselightmaptexture = false;
12880         rsurface.texture = NULL;
12881         rsurface.rtlight = NULL;
12882         numsurfacelist = 0;
12883         // add visible surfaces to draw list
12884         for (i = 0;i < model->nummodelsurfaces;i++)
12885         {
12886                 j = model->sortedmodelsurfaces[i];
12887                 if (r_refdef.viewcache.world_surfacevisible[j])
12888                         r_surfacelist[numsurfacelist++] = surfaces + j;
12889         }
12890         // update lightmaps if needed
12891         if (model->brushq1.firstrender)
12892         {
12893                 model->brushq1.firstrender = false;
12894                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12895                         if (update[j])
12896                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12897         }
12898         else if (update)
12899         {
12900                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12901                         if (r_refdef.viewcache.world_surfacevisible[j])
12902                                 if (update[j])
12903                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12904         }
12905         // don't do anything if there were no surfaces
12906         if (!numsurfacelist)
12907         {
12908                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12909                 return;
12910         }
12911         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12912         GL_AlphaTest(false);
12913
12914         // add to stats if desired
12915         if (r_speeds.integer && !skysurfaces && !depthonly)
12916         {
12917                 r_refdef.stats.world_surfaces += numsurfacelist;
12918                 for (j = 0;j < numsurfacelist;j++)
12919                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
12920         }
12921
12922         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12923 }
12924
12925 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12926 {
12927         int i, j, endj, flagsmask;
12928         dp_model_t *model = ent->model;
12929         msurface_t *surfaces;
12930         unsigned char *update;
12931         int numsurfacelist = 0;
12932         if (model == NULL)
12933                 return;
12934
12935         if (r_maxsurfacelist < model->num_surfaces)
12936         {
12937                 r_maxsurfacelist = model->num_surfaces;
12938                 if (r_surfacelist)
12939                         Mem_Free((msurface_t **)r_surfacelist);
12940                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12941         }
12942
12943         // if the model is static it doesn't matter what value we give for
12944         // wantnormals and wanttangents, so this logic uses only rules applicable
12945         // to a model, knowing that they are meaningless otherwise
12946         if (ent == r_refdef.scene.worldentity)
12947                 RSurf_ActiveWorldEntity();
12948         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12949                 RSurf_ActiveModelEntity(ent, false, false, false);
12950         else if (prepass)
12951                 RSurf_ActiveModelEntity(ent, true, true, true);
12952         else if (depthonly)
12953         {
12954                 switch (vid.renderpath)
12955                 {
12956                 case RENDERPATH_GL20:
12957                 case RENDERPATH_CGGL:
12958                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12959                         break;
12960                 case RENDERPATH_GL13:
12961                 case RENDERPATH_GL11:
12962                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12963                         break;
12964                 }
12965         }
12966         else
12967         {
12968                 switch (vid.renderpath)
12969                 {
12970                 case RENDERPATH_GL20:
12971                 case RENDERPATH_CGGL:
12972                         RSurf_ActiveModelEntity(ent, true, true, false);
12973                         break;
12974                 case RENDERPATH_GL13:
12975                 case RENDERPATH_GL11:
12976                         RSurf_ActiveModelEntity(ent, true, false, false);
12977                         break;
12978                 }
12979         }
12980
12981         surfaces = model->data_surfaces;
12982         update = model->brushq1.lightmapupdateflags;
12983
12984         // update light styles
12985         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12986         {
12987                 model_brush_lightstyleinfo_t *style;
12988                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12989                 {
12990                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12991                         {
12992                                 int *list = style->surfacelist;
12993                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12994                                 for (j = 0;j < style->numsurfaces;j++)
12995                                         update[list[j]] = true;
12996                         }
12997                 }
12998         }
12999
13000         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13001
13002         if (debug)
13003         {
13004                 R_DrawDebugModel();
13005                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13006                 return;
13007         }
13008
13009         rsurface.lightmaptexture = NULL;
13010         rsurface.deluxemaptexture = NULL;
13011         rsurface.uselightmaptexture = false;
13012         rsurface.texture = NULL;
13013         rsurface.rtlight = NULL;
13014         numsurfacelist = 0;
13015         // add visible surfaces to draw list
13016         for (i = 0;i < model->nummodelsurfaces;i++)
13017                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
13018         // don't do anything if there were no surfaces
13019         if (!numsurfacelist)
13020         {
13021                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13022                 return;
13023         }
13024         // update lightmaps if needed
13025         if (update)
13026         {
13027                 int updated = 0;
13028                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13029                 {
13030                         if (update[j])
13031                         {
13032                                 updated++;
13033                                 R_BuildLightMap(ent, surfaces + j);
13034                         }
13035                 }
13036         }
13037         if (update)
13038                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13039                         if (update[j])
13040                                 R_BuildLightMap(ent, surfaces + j);
13041         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13042         GL_AlphaTest(false);
13043
13044         // add to stats if desired
13045         if (r_speeds.integer && !skysurfaces && !depthonly)
13046         {
13047                 r_refdef.stats.entities_surfaces += numsurfacelist;
13048                 for (j = 0;j < numsurfacelist;j++)
13049                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
13050         }
13051
13052         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13053 }
13054
13055 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
13056 {
13057         static texture_t texture;
13058         static msurface_t surface;
13059         const msurface_t *surfacelist = &surface;
13060
13061         // fake enough texture and surface state to render this geometry
13062
13063         texture.update_lastrenderframe = -1; // regenerate this texture
13064         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
13065         texture.currentskinframe = skinframe;
13066         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
13067         texture.offsetmapping = OFFSETMAPPING_OFF;
13068         texture.offsetscale = 1;
13069         texture.specularscalemod = 1;
13070         texture.specularpowermod = 1;
13071
13072         surface.texture = &texture;
13073         surface.num_triangles = numtriangles;
13074         surface.num_firsttriangle = firsttriangle;
13075         surface.num_vertices = numvertices;
13076         surface.num_firstvertex = firstvertex;
13077
13078         // now render it
13079         rsurface.texture = R_GetCurrentTexture(surface.texture);
13080         rsurface.lightmaptexture = NULL;
13081         rsurface.deluxemaptexture = NULL;
13082         rsurface.uselightmaptexture = false;
13083         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
13084 }
13085
13086 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)
13087 {
13088         static msurface_t surface;
13089         const msurface_t *surfacelist = &surface;
13090
13091         // fake enough texture and surface state to render this geometry
13092
13093         surface.texture = texture;
13094         surface.num_triangles = numtriangles;
13095         surface.num_firsttriangle = firsttriangle;
13096         surface.num_vertices = numvertices;
13097         surface.num_firstvertex = firstvertex;
13098
13099         // now render it
13100         rsurface.texture = R_GetCurrentTexture(surface.texture);
13101         rsurface.lightmaptexture = NULL;
13102         rsurface.deluxemaptexture = NULL;
13103         rsurface.uselightmaptexture = false;
13104         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
13105 }