]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
speed up PNG saving by about factor 4 by using fastest zlib mode, and no filters...
[divverent/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28
29 mempool_t *r_main_mempool;
30 rtexturepool_t *r_main_texturepool;
31
32 static int r_frame = 0; ///< used only by R_GetCurrentTexture
33
34 static qboolean r_loadnormalmap;
35 static qboolean r_loadgloss;
36 qboolean r_loadfog;
37 static qboolean r_loaddds;
38 static qboolean r_savedds;
39
40 //
41 // screen size info
42 //
43 r_refdef_t r_refdef;
44
45 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
46 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
47 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
48 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
49 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
50 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
51 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
52 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
53
54 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
55 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
56 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
57 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
58 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
59
60 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
61 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
62 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
63 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
64 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
65 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
66 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
67 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
68 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
69 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
70 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
71 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
72 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
73 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
74 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
75 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
76 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
77 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
78 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
79 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
80 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
81 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
82 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
83 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
84 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
85 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
86 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
87 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
88 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
89 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
90 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
91 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
92 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
93 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
94 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
95 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"};
96 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"};
97 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
98 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
99 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
100 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
101 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"};
102
103 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
104 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
105 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
106 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
107 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
108 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
109 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
110 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
111
112 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)"};
113 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"};
114
115 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
116 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
117 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
118
119 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)"};
120 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
121 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
122 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
123 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
124 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)"};
125 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)"};
126 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)"};
127 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)"};
128
129 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)"};
130 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
131 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"};
132 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
133 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
134
135 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
136 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
137 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
138 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
139
140 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
141 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
142 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
143 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
144 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
145 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
146 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
147
148 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
149 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
150 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
151 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)"};
152
153 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"};
154
155 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"};
156
157 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
158
159 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
160 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
161 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"};
162 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
163 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
164 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
165 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
166
167 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)"};
168
169 extern cvar_t v_glslgamma;
170
171 extern qboolean v_flipped_state;
172
173 static struct r_bloomstate_s
174 {
175         qboolean enabled;
176         qboolean hdr;
177
178         int bloomwidth, bloomheight;
179
180         int screentexturewidth, screentextureheight;
181         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
182
183         int bloomtexturewidth, bloomtextureheight;
184         rtexture_t *texture_bloom;
185
186         // arrays for rendering the screen passes
187         float screentexcoord2f[8];
188         float bloomtexcoord2f[8];
189         float offsettexcoord2f[8];
190
191         r_viewport_t viewport;
192 }
193 r_bloomstate;
194
195 r_waterstate_t r_waterstate;
196
197 /// shadow volume bsp struct with automatically growing nodes buffer
198 svbsp_t r_svbsp;
199
200 rtexture_t *r_texture_blanknormalmap;
201 rtexture_t *r_texture_white;
202 rtexture_t *r_texture_grey128;
203 rtexture_t *r_texture_black;
204 rtexture_t *r_texture_notexture;
205 rtexture_t *r_texture_whitecube;
206 rtexture_t *r_texture_normalizationcube;
207 rtexture_t *r_texture_fogattenuation;
208 rtexture_t *r_texture_gammaramps;
209 unsigned int r_texture_gammaramps_serial;
210 //rtexture_t *r_texture_fogintensity;
211
212 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
213 unsigned int r_numqueries;
214 unsigned int r_maxqueries;
215
216 typedef struct r_qwskincache_s
217 {
218         char name[MAX_QPATH];
219         skinframe_t *skinframe;
220 }
221 r_qwskincache_t;
222
223 static r_qwskincache_t *r_qwskincache;
224 static int r_qwskincache_size;
225
226 /// vertex coordinates for a quad that covers the screen exactly
227 const float r_screenvertex3f[12] =
228 {
229         0, 0, 0,
230         1, 0, 0,
231         1, 1, 0,
232         0, 1, 0
233 };
234
235 extern void R_DrawModelShadows(void);
236
237 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
238 {
239         int i;
240         for (i = 0;i < verts;i++)
241         {
242                 out[0] = in[0] * r;
243                 out[1] = in[1] * g;
244                 out[2] = in[2] * b;
245                 out[3] = in[3];
246                 in += 4;
247                 out += 4;
248         }
249 }
250
251 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
252 {
253         int i;
254         for (i = 0;i < verts;i++)
255         {
256                 out[0] = r;
257                 out[1] = g;
258                 out[2] = b;
259                 out[3] = a;
260                 out += 4;
261         }
262 }
263
264 // FIXME: move this to client?
265 void FOG_clear(void)
266 {
267         if (gamemode == GAME_NEHAHRA)
268         {
269                 Cvar_Set("gl_fogenable", "0");
270                 Cvar_Set("gl_fogdensity", "0.2");
271                 Cvar_Set("gl_fogred", "0.3");
272                 Cvar_Set("gl_foggreen", "0.3");
273                 Cvar_Set("gl_fogblue", "0.3");
274         }
275         r_refdef.fog_density = 0;
276         r_refdef.fog_red = 0;
277         r_refdef.fog_green = 0;
278         r_refdef.fog_blue = 0;
279         r_refdef.fog_alpha = 1;
280         r_refdef.fog_start = 0;
281         r_refdef.fog_end = 16384;
282         r_refdef.fog_height = 1<<30;
283         r_refdef.fog_fadedepth = 128;
284 }
285
286 static void R_BuildBlankTextures(void)
287 {
288         unsigned char data[4];
289         data[2] = 128; // normal X
290         data[1] = 128; // normal Y
291         data[0] = 255; // normal Z
292         data[3] = 128; // height
293         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
294         data[0] = 255;
295         data[1] = 255;
296         data[2] = 255;
297         data[3] = 255;
298         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
299         data[0] = 128;
300         data[1] = 128;
301         data[2] = 128;
302         data[3] = 255;
303         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
304         data[0] = 0;
305         data[1] = 0;
306         data[2] = 0;
307         data[3] = 255;
308         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
309 }
310
311 static void R_BuildNoTexture(void)
312 {
313         int x, y;
314         unsigned char pix[16][16][4];
315         // this makes a light grey/dark grey checkerboard texture
316         for (y = 0;y < 16;y++)
317         {
318                 for (x = 0;x < 16;x++)
319                 {
320                         if ((y < 8) ^ (x < 8))
321                         {
322                                 pix[y][x][0] = 128;
323                                 pix[y][x][1] = 128;
324                                 pix[y][x][2] = 128;
325                                 pix[y][x][3] = 255;
326                         }
327                         else
328                         {
329                                 pix[y][x][0] = 64;
330                                 pix[y][x][1] = 64;
331                                 pix[y][x][2] = 64;
332                                 pix[y][x][3] = 255;
333                         }
334                 }
335         }
336         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
337 }
338
339 static void R_BuildWhiteCube(void)
340 {
341         unsigned char data[6*1*1*4];
342         memset(data, 255, sizeof(data));
343         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
344 }
345
346 static void R_BuildNormalizationCube(void)
347 {
348         int x, y, side;
349         vec3_t v;
350         vec_t s, t, intensity;
351 #define NORMSIZE 64
352         unsigned char *data;
353         data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
354         for (side = 0;side < 6;side++)
355         {
356                 for (y = 0;y < NORMSIZE;y++)
357                 {
358                         for (x = 0;x < NORMSIZE;x++)
359                         {
360                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
361                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
362                                 switch(side)
363                                 {
364                                 default:
365                                 case 0:
366                                         v[0] = 1;
367                                         v[1] = -t;
368                                         v[2] = -s;
369                                         break;
370                                 case 1:
371                                         v[0] = -1;
372                                         v[1] = -t;
373                                         v[2] = s;
374                                         break;
375                                 case 2:
376                                         v[0] = s;
377                                         v[1] = 1;
378                                         v[2] = t;
379                                         break;
380                                 case 3:
381                                         v[0] = s;
382                                         v[1] = -1;
383                                         v[2] = -t;
384                                         break;
385                                 case 4:
386                                         v[0] = s;
387                                         v[1] = -t;
388                                         v[2] = 1;
389                                         break;
390                                 case 5:
391                                         v[0] = -s;
392                                         v[1] = -t;
393                                         v[2] = -1;
394                                         break;
395                                 }
396                                 intensity = 127.0f / sqrt(DotProduct(v, v));
397                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
398                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
399                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
400                                 data[((side*64+y)*64+x)*4+3] = 255;
401                         }
402                 }
403         }
404         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
405         Mem_Free(data);
406 }
407
408 static void R_BuildFogTexture(void)
409 {
410         int x, b;
411 #define FOGWIDTH 256
412         unsigned char data1[FOGWIDTH][4];
413         //unsigned char data2[FOGWIDTH][4];
414         double d, r, alpha;
415
416         r_refdef.fogmasktable_start = r_refdef.fog_start;
417         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
418         r_refdef.fogmasktable_range = r_refdef.fogrange;
419         r_refdef.fogmasktable_density = r_refdef.fog_density;
420
421         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
422         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
423         {
424                 d = (x * r - r_refdef.fogmasktable_start);
425                 if(developer_extra.integer)
426                         Con_DPrintf("%f ", d);
427                 d = max(0, d);
428                 if (r_fog_exp2.integer)
429                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
430                 else
431                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
432                 if(developer_extra.integer)
433                         Con_DPrintf(" : %f ", alpha);
434                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
435                 if(developer_extra.integer)
436                         Con_DPrintf(" = %f\n", alpha);
437                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
438         }
439
440         for (x = 0;x < FOGWIDTH;x++)
441         {
442                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
443                 data1[x][0] = b;
444                 data1[x][1] = b;
445                 data1[x][2] = b;
446                 data1[x][3] = 255;
447                 //data2[x][0] = 255 - b;
448                 //data2[x][1] = 255 - b;
449                 //data2[x][2] = 255 - b;
450                 //data2[x][3] = 255;
451         }
452         if (r_texture_fogattenuation)
453         {
454                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
455                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
456         }
457         else
458         {
459                 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);
460                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
461         }
462 }
463
464 //=======================================================================================================================================================
465
466 static const char *builtinshaderstring =
467 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
468 "// written by Forest 'LordHavoc' Hale\n"
469 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
470 "\n"
471 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
472 "# define USEFOG\n"
473 "#endif\n"
474 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
475 "#define USELIGHTMAP\n"
476 "#endif\n"
477 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING)\n"
478 "#define USEEYEVECTOR\n"
479 "#endif\n"
480 "\n"
481 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
482 "# extension GL_ARB_texture_rectangle : enable\n"
483 "#endif\n"
484 "\n"
485 "#ifdef USESHADOWMAP2D\n"
486 "# ifdef GL_EXT_gpu_shader4\n"
487 "#   extension GL_EXT_gpu_shader4 : enable\n"
488 "# endif\n"
489 "# ifdef GL_ARB_texture_gather\n"
490 "#   extension GL_ARB_texture_gather : enable\n"
491 "# else\n"
492 "#   ifdef GL_AMD_texture_texture4\n"
493 "#     extension GL_AMD_texture_texture4 : enable\n"
494 "#   endif\n"
495 "# endif\n"
496 "#endif\n"
497 "\n"
498 "#ifdef USESHADOWMAPCUBE\n"
499 "# extension GL_EXT_gpu_shader4 : enable\n"
500 "#endif\n"
501 "\n"
502 "//#ifdef USESHADOWSAMPLER\n"
503 "//# extension GL_ARB_shadow : enable\n"
504 "//#endif\n"
505 "\n"
506 "//#ifdef __GLSL_CG_DATA_TYPES\n"
507 "//# define myhalf half\n"
508 "//# define myhalf2 half2\n"
509 "//# define myhalf3 half3\n"
510 "//# define myhalf4 half4\n"
511 "//#else\n"
512 "# define myhalf float\n"
513 "# define myhalf2 vec2\n"
514 "# define myhalf3 vec3\n"
515 "# define myhalf4 vec4\n"
516 "//#endif\n"
517 "\n"
518 "#ifdef VERTEX_SHADER\n"
519 "uniform mat4 ModelViewProjectionMatrix;\n"
520 "#endif\n"
521 "\n"
522 "#ifdef MODE_DEPTH_OR_SHADOW\n"
523 "#ifdef VERTEX_SHADER\n"
524 "void main(void)\n"
525 "{\n"
526 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
527 "}\n"
528 "#endif\n"
529 "#else // !MODE_DEPTH_ORSHADOW\n"
530 "\n"
531 "\n"
532 "\n"
533 "\n"
534 "#ifdef MODE_SHOWDEPTH\n"
535 "#ifdef VERTEX_SHADER\n"
536 "void main(void)\n"
537 "{\n"
538 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
539 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
540 "}\n"
541 "#endif\n"
542 "\n"
543 "#ifdef FRAGMENT_SHADER\n"
544 "void main(void)\n"
545 "{\n"
546 "       gl_FragColor = gl_Color;\n"
547 "}\n"
548 "#endif\n"
549 "#else // !MODE_SHOWDEPTH\n"
550 "\n"
551 "\n"
552 "\n"
553 "\n"
554 "#ifdef MODE_POSTPROCESS\n"
555 "varying vec2 TexCoord1;\n"
556 "varying vec2 TexCoord2;\n"
557 "\n"
558 "#ifdef VERTEX_SHADER\n"
559 "void main(void)\n"
560 "{\n"
561 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
562 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
563 "#ifdef USEBLOOM\n"
564 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
565 "#endif\n"
566 "}\n"
567 "#endif\n"
568 "\n"
569 "#ifdef FRAGMENT_SHADER\n"
570 "uniform sampler2D Texture_First;\n"
571 "#ifdef USEBLOOM\n"
572 "uniform sampler2D Texture_Second;\n"
573 "#endif\n"
574 "#ifdef USEGAMMARAMPS\n"
575 "uniform sampler2D Texture_GammaRamps;\n"
576 "#endif\n"
577 "#ifdef USESATURATION\n"
578 "uniform float Saturation;\n"
579 "#endif\n"
580 "#ifdef USEVIEWTINT\n"
581 "uniform vec4 ViewTintColor;\n"
582 "#endif\n"
583 "//uncomment these if you want to use them:\n"
584 "uniform vec4 UserVec1;\n"
585 "// uniform vec4 UserVec2;\n"
586 "// uniform vec4 UserVec3;\n"
587 "// uniform vec4 UserVec4;\n"
588 "// uniform float ClientTime;\n"
589 "uniform vec2 PixelSize;\n"
590 "void main(void)\n"
591 "{\n"
592 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
593 "#ifdef USEBLOOM\n"
594 "       gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
595 "#endif\n"
596 "#ifdef USEVIEWTINT\n"
597 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
598 "#endif\n"
599 "\n"
600 "#ifdef USEPOSTPROCESSING\n"
601 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
602 "// 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"
603 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
604 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
605 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
606 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
607 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
608 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
609 "#endif\n"
610 "\n"
611 "#ifdef USESATURATION\n"
612 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
613 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
614 "       //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
615 "       gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
616 "#endif\n"
617 "\n"
618 "#ifdef USEGAMMARAMPS\n"
619 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
620 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
621 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
622 "#endif\n"
623 "}\n"
624 "#endif\n"
625 "#else // !MODE_POSTPROCESS\n"
626 "\n"
627 "\n"
628 "\n"
629 "\n"
630 "#ifdef MODE_GENERIC\n"
631 "#ifdef USEDIFFUSE\n"
632 "varying vec2 TexCoord1;\n"
633 "#endif\n"
634 "#ifdef USESPECULAR\n"
635 "varying vec2 TexCoord2;\n"
636 "#endif\n"
637 "#ifdef VERTEX_SHADER\n"
638 "void main(void)\n"
639 "{\n"
640 "       gl_FrontColor = gl_Color;\n"
641 "#ifdef USEDIFFUSE\n"
642 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
643 "#endif\n"
644 "#ifdef USESPECULAR\n"
645 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
646 "#endif\n"
647 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
648 "}\n"
649 "#endif\n"
650 "\n"
651 "#ifdef FRAGMENT_SHADER\n"
652 "#ifdef USEDIFFUSE\n"
653 "uniform sampler2D Texture_First;\n"
654 "#endif\n"
655 "#ifdef USESPECULAR\n"
656 "uniform sampler2D Texture_Second;\n"
657 "#endif\n"
658 "\n"
659 "void main(void)\n"
660 "{\n"
661 "       gl_FragColor = gl_Color;\n"
662 "#ifdef USEDIFFUSE\n"
663 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
664 "#endif\n"
665 "\n"
666 "#ifdef USESPECULAR\n"
667 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
668 "# ifdef USECOLORMAPPING\n"
669 "       gl_FragColor *= tex2;\n"
670 "# endif\n"
671 "# ifdef USEGLOW\n"
672 "       gl_FragColor += tex2;\n"
673 "# endif\n"
674 "# ifdef USEVERTEXTEXTUREBLEND\n"
675 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
676 "# endif\n"
677 "#endif\n"
678 "}\n"
679 "#endif\n"
680 "#else // !MODE_GENERIC\n"
681 "\n"
682 "\n"
683 "\n"
684 "\n"
685 "#ifdef MODE_BLOOMBLUR\n"
686 "varying TexCoord;\n"
687 "#ifdef VERTEX_SHADER\n"
688 "void main(void)\n"
689 "{\n"
690 "       gl_FrontColor = gl_Color;\n"
691 "       TexCoord = gl_MultiTexCoord0.xy;\n"
692 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
693 "}\n"
694 "#endif\n"
695 "\n"
696 "#ifdef FRAGMENT_SHADER\n"
697 "uniform sampler2D Texture_First;\n"
698 "uniform vec4 BloomBlur_Parameters;\n"
699 "\n"
700 "void main(void)\n"
701 "{\n"
702 "       int i;\n"
703 "       vec2 tc = TexCoord;\n"
704 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
705 "       tc += BloomBlur_Parameters.xy;\n"
706 "       for (i = 1;i < SAMPLES;i++)\n"
707 "       {\n"
708 "               color += texture2D(Texture_First, tc).rgb;\n"
709 "               tc += BloomBlur_Parameters.xy;\n"
710 "       }\n"
711 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
712 "}\n"
713 "#endif\n"
714 "#else // !MODE_BLOOMBLUR\n"
715 "#ifdef MODE_REFRACTION\n"
716 "varying vec2 TexCoord;\n"
717 "varying vec4 ModelViewProjectionPosition;\n"
718 "uniform mat4 TexMatrix;\n"
719 "#ifdef VERTEX_SHADER\n"
720 "\n"
721 "void main(void)\n"
722 "{\n"
723 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
724 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
725 "       ModelViewProjectionPosition = gl_Position;\n"
726 "}\n"
727 "#endif\n"
728 "\n"
729 "#ifdef FRAGMENT_SHADER\n"
730 "uniform sampler2D Texture_Normal;\n"
731 "uniform sampler2D Texture_Refraction;\n"
732 "uniform sampler2D Texture_Reflection;\n"
733 "\n"
734 "uniform vec4 DistortScaleRefractReflect;\n"
735 "uniform vec4 ScreenScaleRefractReflect;\n"
736 "uniform vec4 ScreenCenterRefractReflect;\n"
737 "uniform vec4 RefractColor;\n"
738 "uniform vec4 ReflectColor;\n"
739 "uniform float ReflectFactor;\n"
740 "uniform float ReflectOffset;\n"
741 "\n"
742 "void main(void)\n"
743 "{\n"
744 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
745 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
746 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
747 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
748 "       // FIXME temporary hack to detect the case that the reflection\n"
749 "       // gets blackened at edges due to leaving the area that contains actual\n"
750 "       // content.\n"
751 "       // Remove this 'ack once we have a better way to stop this thing from\n"
752 "       // 'appening.\n"
753 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
754 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
755 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
756 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
757 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
758 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
759 "}\n"
760 "#endif\n"
761 "#else // !MODE_REFRACTION\n"
762 "\n"
763 "\n"
764 "\n"
765 "\n"
766 "#ifdef MODE_WATER\n"
767 "varying vec2 TexCoord;\n"
768 "varying vec3 EyeVector;\n"
769 "varying vec4 ModelViewProjectionPosition;\n"
770 "#ifdef VERTEX_SHADER\n"
771 "uniform vec3 EyePosition;\n"
772 "uniform mat4 TexMatrix;\n"
773 "\n"
774 "void main(void)\n"
775 "{\n"
776 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
777 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
778 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
779 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
780 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
781 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
782 "       ModelViewProjectionPosition = gl_Position;\n"
783 "}\n"
784 "#endif\n"
785 "\n"
786 "#ifdef FRAGMENT_SHADER\n"
787 "uniform sampler2D Texture_Normal;\n"
788 "uniform sampler2D Texture_Refraction;\n"
789 "uniform sampler2D Texture_Reflection;\n"
790 "\n"
791 "uniform vec4 DistortScaleRefractReflect;\n"
792 "uniform vec4 ScreenScaleRefractReflect;\n"
793 "uniform vec4 ScreenCenterRefractReflect;\n"
794 "uniform vec4 RefractColor;\n"
795 "uniform vec4 ReflectColor;\n"
796 "uniform float ReflectFactor;\n"
797 "uniform float ReflectOffset;\n"
798 "\n"
799 "void main(void)\n"
800 "{\n"
801 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
802 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
803 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
804 "       vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
805 "       // FIXME temporary hack to detect the case that the reflection\n"
806 "       // gets blackened at edges due to leaving the area that contains actual\n"
807 "       // content.\n"
808 "       // Remove this 'ack once we have a better way to stop this thing from\n"
809 "       // 'appening.\n"
810 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
811 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
812 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
813 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
814 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
815 "       f       = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
816 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
817 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
818 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
819 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
820 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
821 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
822 "}\n"
823 "#endif\n"
824 "#else // !MODE_WATER\n"
825 "\n"
826 "\n"
827 "\n"
828 "\n"
829 "// common definitions between vertex shader and fragment shader:\n"
830 "\n"
831 "varying vec2 TexCoord;\n"
832 "#ifdef USEVERTEXTEXTUREBLEND\n"
833 "varying vec2 TexCoord2;\n"
834 "#endif\n"
835 "#ifdef USELIGHTMAP\n"
836 "varying vec2 TexCoordLightmap;\n"
837 "#endif\n"
838 "\n"
839 "#ifdef MODE_LIGHTSOURCE\n"
840 "varying vec3 CubeVector;\n"
841 "#endif\n"
842 "\n"
843 "#ifdef MODE_LIGHTSOURCE\n"
844 "varying vec3 LightVector;\n"
845 "#endif\n"
846 "#if defined(MODE_LIGHTDIRECTION)\n"
847 "varying vec3 LightVector;\n"
848 "#endif\n"
849 "\n"
850 "#ifdef USEEYEVECTOR\n"
851 "varying vec3 EyeVector;\n"
852 "#endif\n"
853 "#ifdef USEFOG\n"
854 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
855 "#endif\n"
856 "\n"
857 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
858 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
859 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
860 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
861 "#endif\n"
862 "\n"
863 "#ifdef USEREFLECTION\n"
864 "varying vec4 ModelViewProjectionPosition;\n"
865 "#endif\n"
866 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
867 "uniform vec3 LightPosition;\n"
868 "varying vec4 ModelViewPosition;\n"
869 "#endif\n"
870 "\n"
871 "#ifdef MODE_LIGHTSOURCE\n"
872 "uniform vec3 LightPosition;\n"
873 "#endif\n"
874 "uniform vec3 EyePosition;\n"
875 "#ifdef MODE_LIGHTDIRECTION\n"
876 "uniform vec3 LightDir;\n"
877 "#endif\n"
878 "uniform vec4 FogPlane;\n"
879 "\n"
880 "\n"
881 "\n"
882 "\n"
883 "\n"
884 "// 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"
885 "\n"
886 "// fragment shader specific:\n"
887 "#ifdef FRAGMENT_SHADER\n"
888 "\n"
889 "uniform sampler2D Texture_Normal;\n"
890 "uniform sampler2D Texture_Color;\n"
891 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
892 "uniform sampler2D Texture_Gloss;\n"
893 "//#endif\n"
894 "#ifdef USEGLOW\n"
895 "uniform sampler2D Texture_Glow;\n"
896 "#endif\n"
897 "#ifdef USEVERTEXTEXTUREBLEND\n"
898 "uniform sampler2D Texture_SecondaryNormal;\n"
899 "uniform sampler2D Texture_SecondaryColor;\n"
900 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
901 "uniform sampler2D Texture_SecondaryGloss;\n"
902 "//#endif\n"
903 "#ifdef USEGLOW\n"
904 "uniform sampler2D Texture_SecondaryGlow;\n"
905 "#endif\n"
906 "#endif\n"
907 "#ifdef USECOLORMAPPING\n"
908 "uniform sampler2D Texture_Pants;\n"
909 "uniform sampler2D Texture_Shirt;\n"
910 "#endif\n"
911 "#ifdef USEFOG\n"
912 "uniform sampler2D Texture_FogMask;\n"
913 "#endif\n"
914 "#ifdef USELIGHTMAP\n"
915 "uniform sampler2D Texture_Lightmap;\n"
916 "#endif\n"
917 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
918 "uniform sampler2D Texture_Deluxemap;\n"
919 "#endif\n"
920 "#ifdef USEREFLECTION\n"
921 "uniform sampler2D Texture_Reflection;\n"
922 "#endif\n"
923 "\n"
924 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
925 "uniform sampler2DRect Texture_ScreenDepth;\n"
926 "uniform sampler2DRect Texture_ScreenNormalMap;\n"
927 "#endif\n"
928 "#ifdef USEDEFERREDLIGHTMAP\n"
929 "uniform sampler2DRect Texture_ScreenDiffuse;\n"
930 "uniform sampler2DRect Texture_ScreenSpecular;\n"
931 "#endif\n"
932 "\n"
933 "uniform myhalf3 Color_Pants;\n"
934 "uniform myhalf3 Color_Shirt;\n"
935 "uniform myhalf3 FogColor;\n"
936 "\n"
937 "#ifdef USEFOG\n"
938 "uniform float FogRangeRecip;\n"
939 "uniform float FogPlaneViewDist;\n"
940 "uniform float FogHeightFade;\n"
941 "float FogVertex(void)\n"
942 "{\n"
943 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
944 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
945 "       float fogfrac;\n"
946 "#ifdef USEFOGOUTSIDE\n"
947 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
948 "#else\n"
949 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
950 "#endif\n"
951 "       return float(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
952 "}\n"
953 "#endif\n"
954 "\n"
955 "#ifdef USEOFFSETMAPPING\n"
956 "uniform float OffsetMapping_Scale;\n"
957 "vec2 OffsetMapping(vec2 TexCoord)\n"
958 "{\n"
959 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
960 "       // 14 sample relief mapping: linear search and then binary search\n"
961 "       // this basically steps forward a small amount repeatedly until it finds\n"
962 "       // itself inside solid, then jitters forward and back using decreasing\n"
963 "       // amounts to find the impact\n"
964 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
965 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
966 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
967 "       vec3 RT = vec3(TexCoord, 1);\n"
968 "       OffsetVector *= 0.1;\n"
969 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
970 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
971 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
972 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
973 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
974 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
975 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
976 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
977 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
978 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
979 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
980 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
981 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
982 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
983 "       return RT.xy;\n"
984 "#else\n"
985 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
986 "       // this basically moves forward the full distance, and then backs up based\n"
987 "       // on height of samples\n"
988 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
989 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
990 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
991 "       TexCoord += OffsetVector;\n"
992 "       OffsetVector *= 0.333;\n"
993 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
994 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
995 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
996 "       return TexCoord;\n"
997 "#endif\n"
998 "}\n"
999 "#endif // USEOFFSETMAPPING\n"
1000 "\n"
1001 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1002 "uniform sampler2D Texture_Attenuation;\n"
1003 "uniform samplerCube Texture_Cube;\n"
1004 "\n"
1005 "#ifdef USESHADOWMAPRECT\n"
1006 "# ifdef USESHADOWSAMPLER\n"
1007 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1008 "# else\n"
1009 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1010 "# endif\n"
1011 "#endif\n"
1012 "\n"
1013 "#ifdef USESHADOWMAP2D\n"
1014 "# ifdef USESHADOWSAMPLER\n"
1015 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1016 "# else\n"
1017 "uniform sampler2D Texture_ShadowMap2D;\n"
1018 "# endif\n"
1019 "#endif\n"
1020 "\n"
1021 "#ifdef USESHADOWMAPVSDCT\n"
1022 "uniform samplerCube Texture_CubeProjection;\n"
1023 "#endif\n"
1024 "\n"
1025 "#ifdef USESHADOWMAPCUBE\n"
1026 "# ifdef USESHADOWSAMPLER\n"
1027 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1028 "# else\n"
1029 "uniform samplerCube Texture_ShadowMapCube;\n"
1030 "# endif\n"
1031 "#endif\n"
1032 "\n"
1033 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1034 "uniform vec2 ShadowMap_TextureScale;\n"
1035 "uniform vec4 ShadowMap_Parameters;\n"
1036 "#endif\n"
1037 "\n"
1038 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1039 "# ifndef USESHADOWMAPVSDCT\n"
1040 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1041 "{\n"
1042 "       vec3 adir = abs(dir);\n"
1043 "       vec2 tc;\n"
1044 "       vec2 offset;\n"
1045 "       float ma;\n"
1046 "       if (adir.x > adir.y)\n"
1047 "       {\n"
1048 "               if (adir.x > adir.z) // X\n"
1049 "               {\n"
1050 "                       ma = adir.x;\n"
1051 "                       tc = dir.zy;\n"
1052 "                       offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
1053 "               }\n"
1054 "               else // Z\n"
1055 "               {\n"
1056 "                       ma = adir.z;\n"
1057 "                       tc = dir.xy;\n"
1058 "                       offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1059 "               }\n"
1060 "       }\n"
1061 "       else\n"
1062 "       {\n"
1063 "               if (adir.y > adir.z) // Y\n"
1064 "               {\n"
1065 "                       ma = adir.y;\n"
1066 "                       tc = dir.xz;\n"
1067 "                       offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
1068 "               }\n"
1069 "               else // Z\n"
1070 "               {\n"
1071 "                       ma = adir.z;\n"
1072 "                       tc = dir.xy;\n"
1073 "                       offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1074 "               }\n"
1075 "       }\n"
1076 "\n"
1077 "       vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1078 "       stc.xy += offset * ShadowMap_Parameters.y;\n"
1079 "       stc.z += ShadowMap_Parameters.z;\n"
1080 "       return stc;\n"
1081 "}\n"
1082 "# else\n"
1083 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1084 "{\n"
1085 "       vec3 adir = abs(dir);\n"
1086 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1087 "       float ma = max(max(adir.x, adir.y), adir.z);\n"
1088 "       vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1089 "       stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
1090 "       stc.z += ShadowMap_Parameters.z;\n"
1091 "       return stc;\n"
1092 "}\n"
1093 "# endif\n"
1094 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1095 "\n"
1096 "#ifdef USESHADOWMAPCUBE\n"
1097 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1098 "{\n"
1099 "       vec3 adir = abs(dir);\n"
1100 "       return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1101 "}\n"
1102 "#endif\n"
1103 "\n"
1104 "# ifdef USESHADOWMAPRECT\n"
1105 "float ShadowMapCompare(vec3 dir)\n"
1106 "{\n"
1107 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1108 "       float f;\n"
1109 "#  ifdef USESHADOWSAMPLER\n"
1110 "\n"
1111 "#    ifdef USESHADOWMAPPCF\n"
1112 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1113 "       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"
1114 "#    else\n"
1115 "       f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1116 "#    endif\n"
1117 "\n"
1118 "#  else\n"
1119 "\n"
1120 "#    ifdef USESHADOWMAPPCF\n"
1121 "#      if USESHADOWMAPPCF > 1\n"
1122 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1123 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1124 "       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"
1125 "       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"
1126 "       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"
1127 "       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"
1128 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1129 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1130 "#      else\n"
1131 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1132 "       vec2 offset = fract(shadowmaptc.xy);\n"
1133 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1134 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1135 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1136 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1137 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1138 "#      endif\n"
1139 "#    else\n"
1140 "       f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1141 "#    endif\n"
1142 "\n"
1143 "#  endif\n"
1144 "       return f;\n"
1145 "}\n"
1146 "# endif\n"
1147 "\n"
1148 "# ifdef USESHADOWMAP2D\n"
1149 "float ShadowMapCompare(vec3 dir)\n"
1150 "{\n"
1151 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1152 "       float f;\n"
1153 "\n"
1154 "#  ifdef USESHADOWSAMPLER\n"
1155 "#    ifdef USESHADOWMAPPCF\n"
1156 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1157 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1158 "       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"
1159 "#    else\n"
1160 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1161 "#    endif\n"
1162 "#  else\n"
1163 "#    ifdef USESHADOWMAPPCF\n"
1164 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1165 "#      ifdef GL_ARB_texture_gather\n"
1166 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
1167 "#      else\n"
1168 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x,y)*ShadowMap_TextureScale)\n"
1169 "#      endif\n"
1170 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1171 "       center *= ShadowMap_TextureScale;\n"
1172 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1173 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1174 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1175 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1176 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1177 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1178 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1179 "#     else\n"
1180 "#      ifdef GL_EXT_gpu_shader4\n"
1181 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1182 "#      else\n"
1183 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1184 "#      endif\n"
1185 "#      if USESHADOWMAPPCF > 1\n"
1186 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1187 "       center *= ShadowMap_TextureScale;\n"
1188 "       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"
1189 "       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"
1190 "       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"
1191 "       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"
1192 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1193 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1194 "#      else\n"
1195 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1196 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1197 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1198 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1199 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1200 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1201 "#      endif\n"
1202 "#     endif\n"
1203 "#    else\n"
1204 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1205 "#    endif\n"
1206 "#  endif\n"
1207 "       return f;\n"
1208 "}\n"
1209 "# endif\n"
1210 "\n"
1211 "# ifdef USESHADOWMAPCUBE\n"
1212 "float ShadowMapCompare(vec3 dir)\n"
1213 "{\n"
1214 "       // apply depth texture cubemap as light filter\n"
1215 "       vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1216 "       float f;\n"
1217 "#  ifdef USESHADOWSAMPLER\n"
1218 "       f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1219 "#  else\n"
1220 "       f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1221 "#  endif\n"
1222 "       return f;\n"
1223 "}\n"
1224 "# endif\n"
1225 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
1226 "#endif // FRAGMENT_SHADER\n"
1227 "\n"
1228 "\n"
1229 "\n"
1230 "\n"
1231 "#ifdef MODE_DEFERREDGEOMETRY\n"
1232 "#ifdef VERTEX_SHADER\n"
1233 "uniform mat4 TexMatrix;\n"
1234 "#ifdef USEVERTEXTEXTUREBLEND\n"
1235 "uniform mat4 BackgroundTexMatrix;\n"
1236 "#endif\n"
1237 "uniform mat4 ModelViewMatrix;\n"
1238 "void main(void)\n"
1239 "{\n"
1240 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1241 "#ifdef USEVERTEXTEXTUREBLEND\n"
1242 "       gl_FrontColor = gl_Color;\n"
1243 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1244 "#endif\n"
1245 "\n"
1246 "       // transform unnormalized eye direction into tangent space\n"
1247 "#ifdef USEOFFSETMAPPING\n"
1248 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1249 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1250 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1251 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1252 "#endif\n"
1253 "\n"
1254 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1255 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1256 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1257 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1258 "}\n"
1259 "#endif // VERTEX_SHADER\n"
1260 "\n"
1261 "#ifdef FRAGMENT_SHADER\n"
1262 "void main(void)\n"
1263 "{\n"
1264 "#ifdef USEOFFSETMAPPING\n"
1265 "       // apply offsetmapping\n"
1266 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1267 "#define TexCoord TexCoordOffset\n"
1268 "#endif\n"
1269 "\n"
1270 "#ifdef USEALPHAKILL\n"
1271 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1272 "               discard;\n"
1273 "#endif\n"
1274 "\n"
1275 "#ifdef USEVERTEXTEXTUREBLEND\n"
1276 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1277 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1278 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1279 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1280 "#endif\n"
1281 "\n"
1282 "#ifdef USEVERTEXTEXTUREBLEND\n"
1283 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1284 "#else\n"
1285 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1286 "#endif\n"
1287 "\n"
1288 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), 1);\n"
1289 "}\n"
1290 "#endif // FRAGMENT_SHADER\n"
1291 "#else // !MODE_DEFERREDGEOMETRY\n"
1292 "\n"
1293 "\n"
1294 "\n"
1295 "\n"
1296 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1297 "#ifdef VERTEX_SHADER\n"
1298 "uniform mat4 ModelViewMatrix;\n"
1299 "void main(void)\n"
1300 "{\n"
1301 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1302 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1303 "}\n"
1304 "#endif // VERTEX_SHADER\n"
1305 "\n"
1306 "#ifdef FRAGMENT_SHADER\n"
1307 "uniform mat4 ViewToLight;\n"
1308 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1309 "uniform vec2 ScreenToDepth;\n"
1310 "uniform myhalf3 DeferredColor_Ambient;\n"
1311 "uniform myhalf3 DeferredColor_Diffuse;\n"
1312 "#ifdef USESPECULAR\n"
1313 "uniform myhalf3 DeferredColor_Specular;\n"
1314 "uniform myhalf SpecularPower;\n"
1315 "#endif\n"
1316 "void main(void)\n"
1317 "{\n"
1318 "       // calculate viewspace pixel position\n"
1319 "       vec3 position;\n"
1320 "       position.z = ScreenToDepth.y / (texture2DRect(Texture_ScreenDepth, gl_FragCoord.xy).r + ScreenToDepth.x);\n"
1321 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1322 "       // decode viewspace pixel normal\n"
1323 "       myhalf4 normalmap = texture2DRect(Texture_ScreenNormalMap, gl_FragCoord.xy);\n"
1324 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1325 "       // surfacenormal = pixel normal in viewspace\n"
1326 "       // LightVector = pixel to light in viewspace\n"
1327 "       // CubeVector = position in lightspace\n"
1328 "       // eyevector = pixel to view in viewspace\n"
1329 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1330 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1331 "#ifdef USEDIFFUSE\n"
1332 "       // calculate diffuse shading\n"
1333 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1334 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1335 "#endif\n"
1336 "#ifdef USESPECULAR\n"
1337 "       // calculate directional shading\n"
1338 "       vec3 eyevector = position * -1.0;\n"
1339 "#  ifdef USEEXACTSPECULARMATH\n"
1340 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
1341 "#  else\n"
1342 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1343 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1344 "#  endif\n"
1345 "#endif\n"
1346 "\n"
1347 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1348 "       fade *= ShadowMapCompare(CubeVector);\n"
1349 "#endif\n"
1350 "\n"
1351 "#ifdef USEDIFFUSE\n"
1352 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1353 "#else\n"
1354 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1355 "#endif\n"
1356 "#ifdef USESPECULAR\n"
1357 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1358 "#else\n"
1359 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1360 "#endif\n"
1361 "\n"
1362 "# ifdef USECUBEFILTER\n"
1363 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1364 "       gl_FragData[0] *= cubecolor;\n"
1365 "       gl_FragData[1] *= cubecolor;\n"
1366 "# endif\n"
1367 "}\n"
1368 "#endif // FRAGMENT_SHADER\n"
1369 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1370 "\n"
1371 "\n"
1372 "\n"
1373 "\n"
1374 "#ifdef VERTEX_SHADER\n"
1375 "uniform mat4 TexMatrix;\n"
1376 "#ifdef USEVERTEXTEXTUREBLEND\n"
1377 "uniform mat4 BackgroundTexMatrix;\n"
1378 "#endif\n"
1379 "#ifdef MODE_LIGHTSOURCE\n"
1380 "uniform mat4 ModelToLight;\n"
1381 "#endif\n"
1382 "void main(void)\n"
1383 "{\n"
1384 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1385 "       gl_FrontColor = gl_Color;\n"
1386 "#endif\n"
1387 "       // copy the surface texcoord\n"
1388 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1389 "#ifdef USEVERTEXTEXTUREBLEND\n"
1390 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1391 "#endif\n"
1392 "#ifdef USELIGHTMAP\n"
1393 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1394 "#endif\n"
1395 "\n"
1396 "#ifdef MODE_LIGHTSOURCE\n"
1397 "       // transform vertex position into light attenuation/cubemap space\n"
1398 "       // (-1 to +1 across the light box)\n"
1399 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1400 "\n"
1401 "# ifdef USEDIFFUSE\n"
1402 "       // transform unnormalized light direction into tangent space\n"
1403 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1404 "       //  normalize it per pixel)\n"
1405 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1406 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1407 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1408 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1409 "# endif\n"
1410 "#endif\n"
1411 "\n"
1412 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1413 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1414 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1415 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1416 "#endif\n"
1417 "\n"
1418 "       // transform unnormalized eye direction into tangent space\n"
1419 "#ifdef USEEYEVECTOR\n"
1420 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1421 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1422 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1423 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1424 "#endif\n"
1425 "\n"
1426 "#ifdef USEFOG\n"
1427 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1428 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1429 "#endif\n"
1430 "\n"
1431 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1432 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1433 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1434 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1435 "#endif\n"
1436 "\n"
1437 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1438 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1439 "\n"
1440 "#ifdef USEREFLECTION\n"
1441 "       ModelViewProjectionPosition = gl_Position;\n"
1442 "#endif\n"
1443 "}\n"
1444 "#endif // VERTEX_SHADER\n"
1445 "\n"
1446 "\n"
1447 "\n"
1448 "\n"
1449 "#ifdef FRAGMENT_SHADER\n"
1450 "#ifdef USEDEFERREDLIGHTMAP\n"
1451 "uniform myhalf3 DeferredMod_Diffuse;\n"
1452 "uniform myhalf3 DeferredMod_Specular;\n"
1453 "#endif\n"
1454 "uniform myhalf3 Color_Ambient;\n"
1455 "uniform myhalf3 Color_Diffuse;\n"
1456 "uniform myhalf3 Color_Specular;\n"
1457 "uniform myhalf SpecularPower;\n"
1458 "#ifdef USEGLOW\n"
1459 "uniform myhalf3 Color_Glow;\n"
1460 "#endif\n"
1461 "uniform myhalf Alpha;\n"
1462 "#ifdef USEREFLECTION\n"
1463 "uniform vec4 DistortScaleRefractReflect;\n"
1464 "uniform vec4 ScreenScaleRefractReflect;\n"
1465 "uniform vec4 ScreenCenterRefractReflect;\n"
1466 "uniform myhalf4 ReflectColor;\n"
1467 "#endif\n"
1468 "#ifdef MODE_LIGHTDIRECTION\n"
1469 "uniform myhalf3 LightColor;\n"
1470 "#endif\n"
1471 "#ifdef MODE_LIGHTSOURCE\n"
1472 "uniform myhalf3 LightColor;\n"
1473 "#endif\n"
1474 "void main(void)\n"
1475 "{\n"
1476 "#ifdef USEOFFSETMAPPING\n"
1477 "       // apply offsetmapping\n"
1478 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1479 "#define TexCoord TexCoordOffset\n"
1480 "#endif\n"
1481 "\n"
1482 "       // combine the diffuse textures (base, pants, shirt)\n"
1483 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1484 "#ifdef USEALPHAKILL\n"
1485 "       if (color.a < 0.5)\n"
1486 "               discard;\n"
1487 "#endif\n"
1488 "       color.a *= Alpha;\n"
1489 "#ifdef USECOLORMAPPING\n"
1490 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1491 "#endif\n"
1492 "#ifdef USEVERTEXTEXTUREBLEND\n"
1493 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1494 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1495 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1496 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1497 "       color.a = 1.0;\n"
1498 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1499 "#endif\n"
1500 "\n"
1501 "       // get the surface normal\n"
1502 "#ifdef USEVERTEXTEXTUREBLEND\n"
1503 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1504 "#else\n"
1505 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1506 "#endif\n"
1507 "\n"
1508 "       // get the material colors\n"
1509 "       myhalf3 diffusetex = color.rgb;\n"
1510 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1511 "# ifdef USEVERTEXTEXTUREBLEND\n"
1512 "       myhalf3 glosstex = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1513 "# else\n"
1514 "       myhalf3 glosstex = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1515 "# endif\n"
1516 "#endif\n"
1517 "\n"
1518 "\n"
1519 "\n"
1520 "\n"
1521 "#ifdef MODE_LIGHTSOURCE\n"
1522 "       // light source\n"
1523 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1524 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1525 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1526 "#ifdef USESPECULAR\n"
1527 "#ifdef USEEXACTSPECULARMATH\n"
1528 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1529 "#else\n"
1530 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1531 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1532 "#endif\n"
1533 "       color.rgb += glosstex * (specular * Color_Specular);\n"
1534 "#endif\n"
1535 "       color.rgb *= LightColor;\n"
1536 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1537 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1538 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1539 "#endif\n"
1540 "# ifdef USECUBEFILTER\n"
1541 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1542 "# endif\n"
1543 "#endif // MODE_LIGHTSOURCE\n"
1544 "\n"
1545 "\n"
1546 "\n"
1547 "\n"
1548 "#ifdef MODE_LIGHTDIRECTION\n"
1549 "#define SHADING\n"
1550 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1551 "#define lightcolor LightColor\n"
1552 "#endif // MODE_LIGHTDIRECTION\n"
1553 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1554 "#define SHADING\n"
1555 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1556 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1557 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1558 "       // convert modelspace light vector to tangentspace\n"
1559 "       myhalf3 lightnormal;\n"
1560 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1561 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1562 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1563 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1564 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1565 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1566 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1567 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1568 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1569 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1570 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1571 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1572 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1573 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1574 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1575 "#define SHADING\n"
1576 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1577 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1578 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1579 "#endif\n"
1580 "\n"
1581 "\n"
1582 "\n"
1583 "\n"
1584 "#ifdef MODE_LIGHTMAP\n"
1585 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1586 "#endif // MODE_LIGHTMAP\n"
1587 "#ifdef MODE_VERTEXCOLOR\n"
1588 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1589 "#endif // MODE_VERTEXCOLOR\n"
1590 "#ifdef MODE_FLATCOLOR\n"
1591 "       color.rgb = diffusetex * Color_Ambient;\n"
1592 "#endif // MODE_FLATCOLOR\n"
1593 "\n"
1594 "\n"
1595 "\n"
1596 "\n"
1597 "#ifdef SHADING\n"
1598 "# ifdef USEDIFFUSE\n"
1599 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1600 "#  ifdef USESPECULAR\n"
1601 "#   ifdef USEEXACTSPECULARMATH\n"
1602 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1603 "#   else\n"
1604 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1605 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1606 "#   endif\n"
1607 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
1608 "#  else\n"
1609 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1610 "#  endif\n"
1611 "# else\n"
1612 "       color.rgb = diffusetex * Color_Ambient;\n"
1613 "# endif\n"
1614 "#endif\n"
1615 "\n"
1616 "#ifdef USEDEFERREDLIGHTMAP\n"
1617 "       color.rgb += diffusetex * myhalf3(texture2DRect(Texture_ScreenDiffuse, gl_FragCoord.xy)) * DeferredMod_Diffuse;\n"
1618 "       color.rgb += glosstex * myhalf3(texture2DRect(Texture_ScreenSpecular, gl_FragCoord.xy)) * DeferredMod_Specular;\n"
1619 "#endif\n"
1620 "\n"
1621 "#ifdef USEGLOW\n"
1622 "#ifdef USEVERTEXTEXTUREBLEND\n"
1623 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1624 "#else\n"
1625 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1626 "#endif\n"
1627 "#endif\n"
1628 "\n"
1629 "#ifdef USEFOG\n"
1630 "#ifdef MODE_LIGHTSOURCE\n"
1631 "       color.rgb *= myhalf(FogVertex());\n"
1632 "#else\n"
1633 "       color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1634 "#endif\n"
1635 "#endif\n"
1636 "\n"
1637 "       // 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"
1638 "#ifdef USEREFLECTION\n"
1639 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1640 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1641 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1642 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1643 "       // FIXME temporary hack to detect the case that the reflection\n"
1644 "       // gets blackened at edges due to leaving the area that contains actual\n"
1645 "       // content.\n"
1646 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1647 "       // 'appening.\n"
1648 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1649 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1650 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1651 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1652 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1653 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1654 "#endif\n"
1655 "\n"
1656 "       gl_FragColor = vec4(color);\n"
1657 "}\n"
1658 "#endif // FRAGMENT_SHADER\n"
1659 "\n"
1660 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1661 "#endif // !MODE_DEFERREDGEOMETRY\n"
1662 "#endif // !MODE_WATER\n"
1663 "#endif // !MODE_REFRACTION\n"
1664 "#endif // !MODE_BLOOMBLUR\n"
1665 "#endif // !MODE_GENERIC\n"
1666 "#endif // !MODE_POSTPROCESS\n"
1667 "#endif // !MODE_SHOWDEPTH\n"
1668 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1669 ;
1670
1671 /*
1672 =========================================================================================================================================================
1673
1674
1675
1676 =========================================================================================================================================================
1677
1678
1679
1680 =========================================================================================================================================================
1681
1682
1683
1684 =========================================================================================================================================================
1685
1686
1687
1688 =========================================================================================================================================================
1689
1690
1691
1692 =========================================================================================================================================================
1693
1694
1695
1696 =========================================================================================================================================================
1697 */
1698
1699 const char *builtincgshaderstring =
1700 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1701 "// written by Forest 'LordHavoc' Hale\n"
1702 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1703 "\n"
1704 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
1705 "# define USEFOG\n"
1706 "#endif\n"
1707 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1708 "#define USELIGHTMAP\n"
1709 "#endif\n"
1710 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING)\n"
1711 "#define USEEYEVECTOR\n"
1712 "#endif\n"
1713 "\n"
1714 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1715 "#ifdef VERTEX_SHADER\n"
1716 "void main\n"
1717 "(\n"
1718 "float4 gl_Vertex : POSITION,\n"
1719 "uniform float4x4 ModelViewProjectionMatrix,\n"
1720 "out float4 gl_Position : POSITION\n"
1721 ")\n"
1722 "{\n"
1723 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1724 "}\n"
1725 "#endif\n"
1726 "#else // !MODE_DEPTH_ORSHADOW\n"
1727 "\n"
1728 "\n"
1729 "\n"
1730 "\n"
1731 "#ifdef MODE_SHOWDEPTH\n"
1732 "#ifdef VERTEX_SHADER\n"
1733 "void main\n"
1734 "(\n"
1735 "float4 gl_Vertex : POSITION,\n"
1736 "uniform float4x4 ModelViewProjectionMatrix,\n"
1737 "out float4 gl_Position : POSITION,\n"
1738 "out float4 gl_FrontColor : COLOR0\n"
1739 ")\n"
1740 "{\n"
1741 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1742 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1743 "}\n"
1744 "#endif\n"
1745 "\n"
1746 "#ifdef FRAGMENT_SHADER\n"
1747 "void main\n"
1748 "(\n"
1749 "float4 gl_FrontColor : COLOR0,\n"
1750 "out float4 gl_FragColor : COLOR\n"
1751 ")\n"
1752 "{\n"
1753 "       gl_FragColor = gl_FrontColor;\n"
1754 "}\n"
1755 "#endif\n"
1756 "#else // !MODE_SHOWDEPTH\n"
1757 "\n"
1758 "\n"
1759 "\n"
1760 "\n"
1761 "#ifdef MODE_POSTPROCESS\n"
1762 "\n"
1763 "#ifdef VERTEX_SHADER\n"
1764 "void main\n"
1765 "(\n"
1766 "float4 gl_Vertex : POSITION,\n"
1767 "uniform float4x4 ModelViewProjectionMatrix,\n"
1768 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1769 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1770 "out float4 gl_Position : POSITION,\n"
1771 "out float2 TexCoord1 : TEXCOORD0,\n"
1772 "out float2 TexCoord2 : TEXCOORD1\n"
1773 ")\n"
1774 "{\n"
1775 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1776 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1777 "#ifdef USEBLOOM\n"
1778 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1779 "#endif\n"
1780 "}\n"
1781 "#endif\n"
1782 "\n"
1783 "#ifdef FRAGMENT_SHADER\n"
1784 "void main\n"
1785 "(\n"
1786 "float2 TexCoord1 : TEXCOORD0,\n"
1787 "float2 TexCoord2 : TEXCOORD1,\n"
1788 "uniform sampler2D Texture_First,\n"
1789 "#ifdef USEBLOOM\n"
1790 "uniform sampler2D Texture_Second,\n"
1791 "#endif\n"
1792 "#ifdef USEGAMMARAMPS\n"
1793 "uniform sampler2D Texture_GammaRamps,\n"
1794 "#endif\n"
1795 "#ifdef USESATURATION\n"
1796 "uniform float Saturation,\n"
1797 "#endif\n"
1798 "#ifdef USEVIEWTINT\n"
1799 "uniform float4 ViewTintColor,\n"
1800 "#endif\n"
1801 "uniform float4 UserVec1,\n"
1802 "uniform float4 UserVec2,\n"
1803 "uniform float4 UserVec3,\n"
1804 "uniform float4 UserVec4,\n"
1805 "uniform float ClientTime,\n"
1806 "uniform float2 PixelSize,\n"
1807 "out float4 gl_FragColor : COLOR\n"
1808 ")\n"
1809 "{\n"
1810 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1811 "#ifdef USEBLOOM\n"
1812 "       gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
1813 "#endif\n"
1814 "#ifdef USEVIEWTINT\n"
1815 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1816 "#endif\n"
1817 "\n"
1818 "#ifdef USEPOSTPROCESSING\n"
1819 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1820 "// 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"
1821 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1822 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1823 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1824 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
1825 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
1826 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
1827 "#endif\n"
1828 "\n"
1829 "#ifdef USESATURATION\n"
1830 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
1831 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
1832 "       //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
1833 "       gl_FragColor.rgb = mix(float3(y), gl_FragColor.rgb, Saturation);\n"
1834 "#endif\n"
1835 "\n"
1836 "#ifdef USEGAMMARAMPS\n"
1837 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
1838 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
1839 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
1840 "#endif\n"
1841 "}\n"
1842 "#endif\n"
1843 "#else // !MODE_POSTPROCESS\n"
1844 "\n"
1845 "\n"
1846 "\n"
1847 "\n"
1848 "#ifdef MODE_GENERIC\n"
1849 "#ifdef VERTEX_SHADER\n"
1850 "void main\n"
1851 "(\n"
1852 "float4 gl_Vertex : POSITION,\n"
1853 "uniform float4x4 ModelViewProjectionMatrix,\n"
1854 "float4 gl_Color : COLOR0,\n"
1855 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1856 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1857 "out float4 gl_Position : POSITION,\n"
1858 "out float4 gl_FrontColor : COLOR,\n"
1859 "out float2 TexCoord1 : TEXCOORD0,\n"
1860 "out float2 TexCoord2 : TEXCOORD1\n"
1861 ")\n"
1862 "{\n"
1863 "       gl_FrontColor = gl_Color;\n"
1864 "#ifdef USEDIFFUSE\n"
1865 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1866 "#endif\n"
1867 "#ifdef USESPECULAR\n"
1868 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1869 "#endif\n"
1870 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1871 "}\n"
1872 "#endif\n"
1873 "\n"
1874 "#ifdef FRAGMENT_SHADER\n"
1875 "\n"
1876 "void main\n"
1877 "(\n"
1878 "float4 gl_FrontColor : COLOR,\n"
1879 "float2 TexCoord1 : TEXCOORD0,\n"
1880 "float2 TexCoord2 : TEXCOORD1,\n"
1881 "#ifdef USEDIFFUSE\n"
1882 "uniform sampler2D Texture_First,\n"
1883 "#endif\n"
1884 "#ifdef USESPECULAR\n"
1885 "uniform sampler2D Texture_Second,\n"
1886 "#endif\n"
1887 "out float4 gl_FragColor : COLOR\n"
1888 ")\n"
1889 "{\n"
1890 "       gl_FragColor = gl_FrontColor;\n"
1891 "#ifdef USEDIFFUSE\n"
1892 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
1893 "#endif\n"
1894 "\n"
1895 "#ifdef USESPECULAR\n"
1896 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
1897 "# ifdef USECOLORMAPPING\n"
1898 "       gl_FragColor *= tex2;\n"
1899 "# endif\n"
1900 "# ifdef USEGLOW\n"
1901 "       gl_FragColor += tex2;\n"
1902 "# endif\n"
1903 "# ifdef USEVERTEXTEXTUREBLEND\n"
1904 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
1905 "# endif\n"
1906 "#endif\n"
1907 "}\n"
1908 "#endif\n"
1909 "#else // !MODE_GENERIC\n"
1910 "\n"
1911 "\n"
1912 "\n"
1913 "\n"
1914 "#ifdef MODE_BLOOMBLUR\n"
1915 "#ifdef VERTEX_SHADER\n"
1916 "void main\n"
1917 "(\n"
1918 "float4 gl_Vertex : POSITION,\n"
1919 "uniform float4x4 ModelViewProjectionMatrix,\n"
1920 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1921 "out float4 gl_Position : POSITION,\n"
1922 "out float2 TexCoord : TEXCOORD0\n"
1923 ")\n"
1924 "{\n"
1925 "       TexCoord = gl_MultiTexCoord0.xy;\n"
1926 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1927 "}\n"
1928 "#endif\n"
1929 "\n"
1930 "#ifdef FRAGMENT_SHADER\n"
1931 "\n"
1932 "void main\n"
1933 "(\n"
1934 "float2 TexCoord : TEXCOORD0,\n"
1935 "uniform sampler2D Texture_First,\n"
1936 "uniform float4 BloomBlur_Parameters,\n"
1937 "out float4 gl_FragColor : COLOR\n"
1938 ")\n"
1939 "{\n"
1940 "       int i;\n"
1941 "       float2 tc = TexCoord;\n"
1942 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
1943 "       tc += BloomBlur_Parameters.xy;\n"
1944 "       for (i = 1;i < SAMPLES;i++)\n"
1945 "       {\n"
1946 "               color += tex2D(Texture_First, tc).rgb;\n"
1947 "               tc += BloomBlur_Parameters.xy;\n"
1948 "       }\n"
1949 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
1950 "}\n"
1951 "#endif\n"
1952 "#else // !MODE_BLOOMBLUR\n"
1953 "#ifdef MODE_REFRACTION\n"
1954 "#ifdef VERTEX_SHADER\n"
1955 "void main\n"
1956 "(\n"
1957 "float4 gl_Vertex : POSITION,\n"
1958 "uniform float4x4 ModelViewProjectionMatrix,\n"
1959 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1960 "uniform mat4 TexMatrix,\n"
1961 "uniform float3 EyePosition,\n"
1962 "out float4 gl_Position : POSITION,\n"
1963 "out float2 TexCoord : TEXCOORD0,\n"
1964 "out float3 EyeVector : TEXCOORD1,\n"
1965 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
1966 ")\n"
1967 "{\n"
1968 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
1969 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1970 "       ModelViewProjectionPosition = gl_Position;\n"
1971 "}\n"
1972 "#endif\n"
1973 "\n"
1974 "#ifdef FRAGMENT_SHADER\n"
1975 "void main\n"
1976 "(\n"
1977 "float2 TexCoord : TEXCOORD0,\n"
1978 "float3 EyeVector : TEXCOORD1,\n"
1979 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
1980 "uniform sampler2D Texture_Normal,\n"
1981 "uniform sampler2D Texture_Refraction,\n"
1982 "uniform sampler2D Texture_Reflection,\n"
1983 "uniform float4 DistortScaleRefractReflect,\n"
1984 "uniform float4 ScreenScaleRefractReflect,\n"
1985 "uniform float4 ScreenCenterRefractReflect,\n"
1986 "uniform float4 RefractColor,\n"
1987 "out float4 gl_FragColor : COLOR\n"
1988 ")\n"
1989 "{\n"
1990 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
1991 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1992 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1993 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
1994 "       // FIXME temporary hack to detect the case that the reflection\n"
1995 "       // gets blackened at edges due to leaving the area that contains actual\n"
1996 "       // content.\n"
1997 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1998 "       // 'appening.\n"
1999 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2000 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2001 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2002 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2003 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2004 "       gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2005 "}\n"
2006 "#endif\n"
2007 "#else // !MODE_REFRACTION\n"
2008 "\n"
2009 "\n"
2010 "\n"
2011 "\n"
2012 "#ifdef MODE_WATER\n"
2013 "#ifdef VERTEX_SHADER\n"
2014 "\n"
2015 "void main\n"
2016 "(\n"
2017 "float4 gl_Vertex : POSITION,\n"
2018 "uniform float4x4 ModelViewProjectionMatrix,\n"
2019 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2020 "uniform mat4 TexMatrix,\n"
2021 "uniform float3 EyePosition,\n"
2022 "out float4 gl_Position : POSITION,\n"
2023 "out float2 TexCoord : TEXCOORD0,\n"
2024 "out float3 EyeVector : TEXCOORD1,\n"
2025 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2026 ")\n"
2027 "{\n"
2028 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2029 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2030 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2031 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2032 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2033 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2034 "       ModelViewProjectionPosition = gl_Position;\n"
2035 "}\n"
2036 "#endif\n"
2037 "\n"
2038 "#ifdef FRAGMENT_SHADER\n"
2039 "void main\n"
2040 "(\n"
2041 "float2 TexCoord : TEXCOORD0,\n"
2042 "float3 EyeVector : TEXCOORD1,\n"
2043 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2044 "uniform sampler2D Texture_Normal,\n"
2045 "uniform sampler2D Texture_Refraction,\n"
2046 "uniform sampler2D Texture_Reflection,\n"
2047 "uniform float4 DistortScaleRefractReflect,\n"
2048 "uniform float4 ScreenScaleRefractReflect,\n"
2049 "uniform float4 ScreenCenterRefractReflect,\n"
2050 "uniform float4 RefractColor,\n"
2051 "uniform float4 ReflectColor,\n"
2052 "uniform float ReflectFactor,\n"
2053 "uniform float ReflectOffset,\n"
2054 "out float4 gl_FragColor : COLOR\n"
2055 ")\n"
2056 "{\n"
2057 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2058 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2059 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2060 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xyxy * DistortScaleRefractReflect;\n"
2061 "       // FIXME temporary hack to detect the case that the reflection\n"
2062 "       // gets blackened at edges due to leaving the area that contains actual\n"
2063 "       // content.\n"
2064 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2065 "       // 'appening.\n"
2066 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2067 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2068 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2069 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2070 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2071 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2072 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2073 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2074 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2075 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2076 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2077 "       gl_FragColor = mix(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2078 "}\n"
2079 "#endif\n"
2080 "#else // !MODE_WATER\n"
2081 "\n"
2082 "\n"
2083 "\n"
2084 "\n"
2085 "// 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"
2086 "\n"
2087 "// fragment shader specific:\n"
2088 "#ifdef FRAGMENT_SHADER\n"
2089 "\n"
2090 "#ifdef USEFOG\n"
2091 "float FogVertex(float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask)\n"
2092 "{\n"
2093 "       float fogfrac;\n"
2094 "#ifdef USEFOGOUTSIDE\n"
2095 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2096 "#else\n"
2097 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2098 "#endif\n"
2099 "       return float(tex2D(Texture_FogMask, half2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
2100 "}\n"
2101 "#endif\n"
2102 "\n"
2103 "#ifdef USEOFFSETMAPPING\n"
2104 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler2D Texture_Normal)\n"
2105 "{\n"
2106 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2107 "       // 14 sample relief mapping: linear search and then binary search\n"
2108 "       // this basically steps forward a small amount repeatedly until it finds\n"
2109 "       // itself inside solid, then jitters forward and back using decreasing\n"
2110 "       // amounts to find the impact\n"
2111 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2112 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2113 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2114 "       float3 RT = float3(TexCoord, 1);\n"
2115 "       OffsetVector *= 0.1;\n"
2116 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2117 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2118 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2119 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2120 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2121 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2122 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2123 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2124 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2125 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2126 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2127 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2128 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2129 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2130 "       return RT.xy;\n"
2131 "#else\n"
2132 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2133 "       // this basically moves forward the full distance, and then backs up based\n"
2134 "       // on height of samples\n"
2135 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2136 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2137 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2138 "       TexCoord += OffsetVector;\n"
2139 "       OffsetVector *= 0.333;\n"
2140 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2141 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2142 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2143 "       return TexCoord;\n"
2144 "#endif\n"
2145 "}\n"
2146 "#endif // USEOFFSETMAPPING\n"
2147 "\n"
2148 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2149 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2150 "# ifndef USESHADOWMAPVSDCT\n"
2151 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2152 "{\n"
2153 "       float3 adir = abs(dir);\n"
2154 "       float2 tc;\n"
2155 "       float2 offset;\n"
2156 "       float ma;\n"
2157 "       if (adir.x > adir.y)\n"
2158 "       {\n"
2159 "               if (adir.x > adir.z) // X\n"
2160 "               {\n"
2161 "                       ma = adir.x;\n"
2162 "                       tc = dir.zy;\n"
2163 "                       offset = float2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
2164 "               }\n"
2165 "               else // Z\n"
2166 "               {\n"
2167 "                       ma = adir.z;\n"
2168 "                       tc = dir.xy;\n"
2169 "                       offset = float2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
2170 "               }\n"
2171 "       }\n"
2172 "       else\n"
2173 "       {\n"
2174 "               if (adir.y > adir.z) // Y\n"
2175 "               {\n"
2176 "                       ma = adir.y;\n"
2177 "                       tc = dir.xz;\n"
2178 "                       offset = float2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
2179 "               }\n"
2180 "               else // Z\n"
2181 "               {\n"
2182 "                       ma = adir.z;\n"
2183 "                       tc = dir.xy;\n"
2184 "                       offset = float2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
2185 "               }\n"
2186 "       }\n"
2187 "\n"
2188 "       float3 stc = float3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2189 "       stc.xy += offset * ShadowMap_Parameters.y;\n"
2190 "       stc.z += ShadowMap_Parameters.z;\n"
2191 "       return stc;\n"
2192 "}\n"
2193 "# else\n"
2194 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2195 "{\n"
2196 "       float3 adir = abs(dir);\n"
2197 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2198 "       float ma = max(max(adir.x, adir.y), adir.z);\n"
2199 "       float3 stc = float3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2200 "       stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
2201 "       stc.z += ShadowMap_Parameters.z;\n"
2202 "       return stc;\n"
2203 "}\n"
2204 "# endif\n"
2205 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2206 "\n"
2207 "#ifdef USESHADOWMAPCUBE\n"
2208 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2209 "{\n"
2210 "    float3 adir = abs(dir);\n"
2211 "    return float4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
2212 "}\n"
2213 "#endif\n"
2214 "\n"
2215 "# ifdef USESHADOWMAPRECT\n"
2216 "#ifdef USESHADOWMAPVSDCT\n"
2217 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2218 "#else\n"
2219 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2220 "#endif\n"
2221 "{\n"
2222 "#ifdef USESHADOWMAPVSDCT\n"
2223 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2224 "#else\n"
2225 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2226 "#endif\n"
2227 "       float f;\n"
2228 "#  ifdef USESHADOWSAMPLER\n"
2229 "\n"
2230 "#    ifdef USESHADOWMAPPCF\n"
2231 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2232 "    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"
2233 "#    else\n"
2234 "    f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2235 "#    endif\n"
2236 "\n"
2237 "#  else\n"
2238 "\n"
2239 "#    ifdef USESHADOWMAPPCF\n"
2240 "#      if USESHADOWMAPPCF > 1\n"
2241 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2242 "    float2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
2243 "    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"
2244 "    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"
2245 "    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"
2246 "    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"
2247 "    float4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
2248 "    f = dot(mix(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2249 "#      else\n"
2250 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2251 "    float2 offset = fract(shadowmaptc.xy);\n"
2252 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2253 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2254 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2255 "    float3 cols = row2 + mix(row1, row3, offset.y);\n"
2256 "    f = dot(mix(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2257 "#      endif\n"
2258 "#    else\n"
2259 "    f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2260 "#    endif\n"
2261 "\n"
2262 "#  endif\n"
2263 "       return f;\n"
2264 "}\n"
2265 "# endif\n"
2266 "\n"
2267 "# ifdef USESHADOWMAP2D\n"
2268 "#ifdef USESHADOWMAPVSDCT\n"
2269 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2270 "#else\n"
2271 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2272 "#endif\n"
2273 "{\n"
2274 "#ifdef USESHADOWMAPVSDCT\n"
2275 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2276 "#else\n"
2277 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2278 "#endif\n"
2279 "    float f;\n"
2280 "\n"
2281 "#  ifdef USESHADOWSAMPLER\n"
2282 "#    ifdef USESHADOWMAPPCF\n"
2283 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, float3(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
2284 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2285 "    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"
2286 "#    else\n"
2287 "    f = shadow2D(Texture_ShadowMap2D, float3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
2288 "#    endif\n"
2289 "#  else\n"
2290 "#    ifdef USESHADOWMAPPCF\n"
2291 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2292 "#      ifdef GL_ARB_texture_gather\n"
2293 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
2294 "#      else\n"
2295 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x,y)*ShadowMap_TextureScale)\n"
2296 "#      endif\n"
2297 "    float2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
2298 "    center *= ShadowMap_TextureScale;\n"
2299 "    float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2300 "    float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2301 "    float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2302 "    float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2303 "    float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2304 "                mix(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2305 "    f = dot(mix(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2306 "#     else\n"
2307 "#      ifdef GL_EXT_gpu_shader4\n"
2308 "#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, ifloat2(x, y)).r\n"
2309 "#      else\n"
2310 "#        define texval(x, y) tex2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
2311 "#      endif\n"
2312 "#      if USESHADOWMAPPCF > 1\n"
2313 "    float2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
2314 "    center *= ShadowMap_TextureScale;\n"
2315 "    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"
2316 "    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"
2317 "    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"
2318 "    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"
2319 "    float4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
2320 "    f = dot(mix(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2321 "#      else\n"
2322 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
2323 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2324 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2325 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2326 "    float3 cols = row2 + mix(row1, row3, offset.y);\n"
2327 "    f = dot(mix(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2328 "#      endif\n"
2329 "#     endif\n"
2330 "#    else\n"
2331 "    f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2332 "#    endif\n"
2333 "#  endif\n"
2334 "    return f;\n"
2335 "}\n"
2336 "# endif\n"
2337 "\n"
2338 "# ifdef USESHADOWMAPCUBE\n"
2339 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2340 "{\n"
2341 "    // apply depth texture cubemap as light filter\n"
2342 "    float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2343 "    float f;\n"
2344 "#  ifdef USESHADOWSAMPLER\n"
2345 "    f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2346 "#  else\n"
2347 "    f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2348 "#  endif\n"
2349 "    return f;\n"
2350 "}\n"
2351 "# endif\n"
2352 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2353 "#endif // FRAGMENT_SHADER\n"
2354 "\n"
2355 "\n"
2356 "\n"
2357 "\n"
2358 "#ifdef MODE_DEFERREDGEOMETRY\n"
2359 "#ifdef VERTEX_SHADER\n"
2360 "void main\n"
2361 "(\n"
2362 "float4 gl_Vertex : POSITION,\n"
2363 "uniform float4x4 ModelViewProjectionMatrix,\n"
2364 "#ifdef USEVERTEXTEXTUREBLEND\n"
2365 "float4 gl_Color : COLOR0,\n"
2366 "#endif\n"
2367 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2368 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2369 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2370 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2371 "uniform mat4 TexMatrix,\n"
2372 "#ifdef USEVERTEXTEXTUREBLEND\n"
2373 "uniform mat4 BackgroundTexMatrix,\n"
2374 "#endif\n"
2375 "uniform mat4 ModelViewMatrix,\n"
2376 "out float4 gl_Position : POSITION,\n"
2377 "out float4 gl_FrontColor : COLOR,\n"
2378 "out float4 TexCoordBoth : TEXCOORD0,\n"
2379 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2380 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2381 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2382 ")\n"
2383 "{\n"
2384 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2385 "#ifdef USEVERTEXTEXTUREBLEND\n"
2386 "       gl_FrontColor = gl_Color;\n"
2387 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2388 "#endif\n"
2389 "\n"
2390 "       // transform unnormalized eye direction into tangent space\n"
2391 "#ifdef USEOFFSETMAPPING\n"
2392 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2393 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2394 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2395 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2396 "#endif\n"
2397 "\n"
2398 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2399 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2400 "       VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2401 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2402 "}\n"
2403 "#endif // VERTEX_SHADER\n"
2404 "\n"
2405 "#ifdef FRAGMENT_SHADER\n"
2406 "void main\n"
2407 "(\n"
2408 "float4 TexCoordBoth : TEXCOORD0,\n"
2409 "float3 EyeVector : TEXCOORD2,\n"
2410 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2411 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2412 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2413 "uniform sampler2D Texture_Normal,\n"
2414 "#ifdef USEALPHAKILL\n"
2415 "uniform sampler2D Texture_Color,\n"
2416 "#endif\n"
2417 "#ifdef USEVERTEXTEXTUREBLEND\n"
2418 "uniform sampler2D Texture_SecondaryNormal,\n"
2419 "#endif\n"
2420 "#ifdef USEOFFSETMAPPING\n"
2421 "uniform float OffsetMapping_Scale,\n"
2422 "#endif\n"
2423 "uniform half SpecularPower,\n"
2424 "out float4 gl_FragColor : COLOR\n"
2425 ")\n"
2426 "{\n"
2427 "       float2 TexCoord = TexCoordBoth.xy;\n"
2428 "#ifdef USEOFFSETMAPPING\n"
2429 "       // apply offsetmapping\n"
2430 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2431 "#define TexCoord TexCoordOffset\n"
2432 "#endif\n"
2433 "\n"
2434 "#ifdef USEALPHAKILL\n"
2435 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2436 "               discard;\n"
2437 "#endif\n"
2438 "\n"
2439 "#ifdef USEVERTEXTEXTUREBLEND\n"
2440 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2441 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2442 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2443 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2444 "#endif\n"
2445 "\n"
2446 "#ifdef USEVERTEXTEXTUREBLEND\n"
2447 "       float3 surfacenormal = mix(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
2448 "#else\n"
2449 "       float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
2450 "#endif\n"
2451 "\n"
2452 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), 1);\n"
2453 "}\n"
2454 "#endif // FRAGMENT_SHADER\n"
2455 "#else // !MODE_DEFERREDGEOMETRY\n"
2456 "\n"
2457 "\n"
2458 "\n"
2459 "\n"
2460 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2461 "#ifdef VERTEX_SHADER\n"
2462 "void main\n"
2463 "(\n"
2464 "float4 gl_Vertex : POSITION,\n"
2465 "uniform float4x4 ModelViewProjectionMatrix,\n"
2466 "uniform mat4 ModelViewMatrix,\n"
2467 "out float4 gl_Position : POSITION,\n"
2468 "out float4 ModelViewPosition : TEXCOORD0\n"
2469 ")\n"
2470 "{\n"
2471 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2472 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2473 "}\n"
2474 "#endif // VERTEX_SHADER\n"
2475 "\n"
2476 "#ifdef FRAGMENT_SHADER\n"
2477 "void main\n"
2478 "(\n"
2479 "float2 Pixel : WPOS,\n"
2480 "float4 ModelViewPosition : TEXCOORD0,\n"
2481 "uniform mat4 ViewToLight,\n"
2482 "uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2483 "uniform float3 LightPosition,\n"
2484 "uniform half3 DeferredColor_Ambient,\n"
2485 "uniform half3 DeferredColor_Diffuse,\n"
2486 "#ifdef USESPECULAR\n"
2487 "uniform half3 DeferredColor_Specular,\n"
2488 "uniform half SpecularPower,\n"
2489 "#endif\n"
2490 "uniform sampler2D Texture_Attenuation,\n"
2491 "uniform samplerRECT Texture_ScreenDepth,\n"
2492 "uniform samplerRECT Texture_ScreenNormalMap,\n"
2493 "\n"
2494 "#ifdef USESHADOWMAPRECT\n"
2495 "# ifdef USESHADOWSAMPLER\n"
2496 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2497 "# else\n"
2498 "uniform samplerRECT Texture_ShadowMapRect,\n"
2499 "# endif\n"
2500 "#endif\n"
2501 "\n"
2502 "#ifdef USESHADOWMAP2D\n"
2503 "# ifdef USESHADOWSAMPLER\n"
2504 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2505 "# else\n"
2506 "uniform sampler2D Texture_ShadowMap2D,\n"
2507 "# endif\n"
2508 "#endif\n"
2509 "\n"
2510 "#ifdef USESHADOWMAPVSDCT\n"
2511 "uniform samplerCUBE Texture_CubeProjection,\n"
2512 "#endif\n"
2513 "\n"
2514 "#ifdef USESHADOWMAPCUBE\n"
2515 "# ifdef USESHADOWSAMPLER\n"
2516 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2517 "# else\n"
2518 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2519 "# endif\n"
2520 "#endif\n"
2521 "\n"
2522 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2523 "uniform float2 ShadowMap_TextureScale,\n"
2524 "uniform float4 ShadowMap_Parameters,\n"
2525 "#endif\n"
2526 "\n"
2527 "out float4 gl_FragData0 : COLOR0,\n"
2528 "out float4 gl_FragData1 : COLOR1\n"
2529 ")\n"
2530 "{\n"
2531 "       // calculate viewspace pixel position\n"
2532 "       float3 position;\n"
2533 "       position.z = ScreenToDepth.y / (texRECT(Texture_ScreenDepth, Pixel).r + ScreenToDepth.x);\n"
2534 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2535 "       // decode viewspace pixel normal\n"
2536 "       half4 normalmap = texRECT(Texture_ScreenNormalMap, Pixel);\n"
2537 "       half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
2538 "       // surfacenormal = pixel normal in viewspace\n"
2539 "       // LightVector = pixel to light in viewspace\n"
2540 "       // CubeVector = position in lightspace\n"
2541 "       // eyevector = pixel to view in viewspace\n"
2542 "       float3 CubeVector = float3(mul(ViewToLight, float4(position,1)));\n"
2543 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2544 "#ifdef USEDIFFUSE\n"
2545 "       // calculate diffuse shading\n"
2546 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2547 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2548 "#endif\n"
2549 "#ifdef USESPECULAR\n"
2550 "       // calculate directional shading\n"
2551 "       float3 eyevector = position * -1.0;\n"
2552 "#  ifdef USEEXACTSPECULARMATH\n"
2553 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
2554 "#  else\n"
2555 "       half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
2556 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
2557 "#  endif\n"
2558 "#endif\n"
2559 "\n"
2560 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2561 "       fade *= ShadowMapCompare(CubeVector,\n"
2562 "# if defined(USESHADOWMAP2D)\n"
2563 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2564 "# endif\n"
2565 "# if defined(USESHADOWMAPRECT)\n"
2566 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2567 "# endif\n"
2568 "# if defined(USESHADOWMAPCUBE)\n"
2569 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2570 "# endif\n"
2571 "\n"
2572 "#ifdef USESHADOWMAPVSDCT\n"
2573 ", Texture_CubeProjection\n"
2574 "#endif\n"
2575 "       );\n"
2576 "#endif\n"
2577 "\n"
2578 "#ifdef USEDIFFUSE\n"
2579 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2580 "#else\n"
2581 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2582 "#endif\n"
2583 "#ifdef USESPECULAR\n"
2584 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2585 "#else\n"
2586 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2587 "#endif\n"
2588 "\n"
2589 "# ifdef USECUBEFILTER\n"
2590 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2591 "       gl_FragData0 *= cubecolor;\n"
2592 "       gl_FragData1 *= cubecolor;\n"
2593 "# endif\n"
2594 "}\n"
2595 "#endif // FRAGMENT_SHADER\n"
2596 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2597 "\n"
2598 "\n"
2599 "\n"
2600 "\n"
2601 "#ifdef VERTEX_SHADER\n"
2602 "void main\n"
2603 "(\n"
2604 "float4 gl_Vertex : POSITION,\n"
2605 "uniform float4x4 ModelViewProjectionMatrix,\n"
2606 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2607 "float4 gl_Color : COLOR0,\n"
2608 "#endif\n"
2609 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2610 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2611 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2612 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2613 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2614 "\n"
2615 "uniform float3 EyePosition,\n"
2616 "uniform mat4 TexMatrix,\n"
2617 "#ifdef USEVERTEXTEXTUREBLEND\n"
2618 "uniform mat4 BackgroundTexMatrix,\n"
2619 "#endif\n"
2620 "#ifdef MODE_LIGHTSOURCE\n"
2621 "uniform mat4 ModelToLight,\n"
2622 "#endif\n"
2623 "#ifdef MODE_LIGHTSOURCE\n"
2624 "uniform float3 LightPosition,\n"
2625 "#endif\n"
2626 "#ifdef MODE_LIGHTDIRECTION\n"
2627 "uniform float3 LightDir,\n"
2628 "#endif\n"
2629 "uniform float4 FogPlane,\n"
2630 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2631 "uniform float3 LightPosition,\n"
2632 "#endif\n"
2633 "\n"
2634 "out float4 gl_FrontColor : COLOR,\n"
2635 "out float4 TexCoordBoth : TEXCOORD0,\n"
2636 "#ifdef USELIGHTMAP\n"
2637 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2638 "#endif\n"
2639 "#ifdef USEEYEVECTOR\n"
2640 "out float3 EyeVector : TEXCOORD2,\n"
2641 "#endif\n"
2642 "#ifdef USEREFLECTION\n"
2643 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2644 "#endif\n"
2645 "#ifdef USEFOG\n"
2646 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2647 "#endif\n"
2648 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2649 "out float3 LightVector : TEXCOORD5,\n"
2650 "#endif\n"
2651 "#ifdef MODE_LIGHTSOURCE\n"
2652 "out float3 CubeVector : TEXCOORD3,\n"
2653 "#endif\n"
2654 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
2655 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2656 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2657 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2658 "#endif\n"
2659 "out float4 gl_Position : POSITION\n"
2660 ")\n"
2661 "{\n"
2662 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2663 "       gl_FrontColor = gl_Color;\n"
2664 "#endif\n"
2665 "       // copy the surface texcoord\n"
2666 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2667 "#ifdef USEVERTEXTEXTUREBLEND\n"
2668 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2669 "#endif\n"
2670 "#ifdef USELIGHTMAP\n"
2671 "       TexCoordLightmap = float2(gl_MultiTexCoord4);\n"
2672 "#endif\n"
2673 "\n"
2674 "#ifdef MODE_LIGHTSOURCE\n"
2675 "       // transform vertex position into light attenuation/cubemap space\n"
2676 "       // (-1 to +1 across the light box)\n"
2677 "       CubeVector = float3(mul(ModelToLight, gl_Vertex));\n"
2678 "\n"
2679 "# ifdef USEDIFFUSE\n"
2680 "       // transform unnormalized light direction into tangent space\n"
2681 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2682 "       //  normalize it per pixel)\n"
2683 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2684 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2685 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2686 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2687 "# endif\n"
2688 "#endif\n"
2689 "\n"
2690 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2691 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2692 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2693 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2694 "#endif\n"
2695 "\n"
2696 "       // transform unnormalized eye direction into tangent space\n"
2697 "#ifdef USEEYEVECTOR\n"
2698 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2699 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2700 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2701 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2702 "#endif\n"
2703 "\n"
2704 "#ifdef USEFOG\n"
2705 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2706 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2707 "#endif\n"
2708 "\n"
2709 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2710 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2711 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2712 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2713 "#endif\n"
2714 "\n"
2715 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2716 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2717 "\n"
2718 "#ifdef USEREFLECTION\n"
2719 "       ModelViewProjectionPosition = gl_Position;\n"
2720 "#endif\n"
2721 "}\n"
2722 "#endif // VERTEX_SHADER\n"
2723 "\n"
2724 "\n"
2725 "\n"
2726 "\n"
2727 "#ifdef FRAGMENT_SHADER\n"
2728 "void main\n"
2729 "(\n"
2730 "#ifdef USEDEFERREDLIGHTMAP\n"
2731 "float2 Pixel : WPOS,\n"
2732 "#endif\n"
2733 "float4 gl_FrontColor : COLOR,\n"
2734 "float4 TexCoordBoth : TEXCOORD0,\n"
2735 "#ifdef USELIGHTMAP\n"
2736 "float2 TexCoordLightmap : TEXCOORD1,\n"
2737 "#endif\n"
2738 "#ifdef USEEYEVECTOR\n"
2739 "float3 EyeVector : TEXCOORD2,\n"
2740 "#endif\n"
2741 "#ifdef USEREFLECTION\n"
2742 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2743 "#endif\n"
2744 "#ifdef USEFOG\n"
2745 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2746 "#endif\n"
2747 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2748 "float3 LightVector : TEXCOORD5,\n"
2749 "#endif\n"
2750 "#ifdef MODE_LIGHTSOURCE\n"
2751 "float3 CubeVector : TEXCOORD3,\n"
2752 "#endif\n"
2753 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2754 "float4 ModelViewPosition : TEXCOORD0,\n"
2755 "#endif\n"
2756 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
2757 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2758 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2759 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2760 "#endif\n"
2761 "\n"
2762 "uniform sampler2D Texture_Normal,\n"
2763 "uniform sampler2D Texture_Color,\n"
2764 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2765 "uniform sampler2D Texture_Gloss,\n"
2766 "#endif\n"
2767 "#ifdef USEGLOW\n"
2768 "uniform sampler2D Texture_Glow,\n"
2769 "#endif\n"
2770 "#ifdef USEVERTEXTEXTUREBLEND\n"
2771 "uniform sampler2D Texture_SecondaryNormal,\n"
2772 "uniform sampler2D Texture_SecondaryColor,\n"
2773 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2774 "uniform sampler2D Texture_SecondaryGloss,\n"
2775 "#endif\n"
2776 "#ifdef USEGLOW\n"
2777 "uniform sampler2D Texture_SecondaryGlow,\n"
2778 "#endif\n"
2779 "#endif\n"
2780 "#ifdef USECOLORMAPPING\n"
2781 "uniform sampler2D Texture_Pants,\n"
2782 "uniform sampler2D Texture_Shirt,\n"
2783 "#endif\n"
2784 "#ifdef USEFOG\n"
2785 "uniform sampler2D Texture_FogMask,\n"
2786 "#endif\n"
2787 "#ifdef USELIGHTMAP\n"
2788 "uniform sampler2D Texture_Lightmap,\n"
2789 "#endif\n"
2790 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2791 "uniform sampler2D Texture_Deluxemap,\n"
2792 "#endif\n"
2793 "#ifdef USEREFLECTION\n"
2794 "uniform sampler2D Texture_Reflection,\n"
2795 "#endif\n"
2796 "\n"
2797 "//#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2798 "uniform samplerRECT Texture_ScreenDepth,\n"
2799 "uniform samplerRECT Texture_ScreenNormalMap,\n"
2800 "//#endif\n"
2801 "#ifdef USEDEFERREDLIGHTMAP\n"
2802 "uniform samplerRECT Texture_ScreenDiffuse,\n"
2803 "uniform samplerRECT Texture_ScreenSpecular,\n"
2804 "#endif\n"
2805 "\n"
2806 "#ifdef USECOLORMAPPING\n"
2807 "uniform half3 Color_Pants,\n"
2808 "uniform half3 Color_Shirt,\n"
2809 "#endif\n"
2810 "#ifdef USEFOG\n"
2811 "uniform float3 FogColor,\n"
2812 "uniform float FogRangeRecip,\n"
2813 "uniform float FogPlaneViewDist,\n"
2814 "uniform float FogHeightFade,\n"
2815 "#endif\n"
2816 "\n"
2817 "#ifdef USEOFFSETMAPPING\n"
2818 "uniform float OffsetMapping_Scale,\n"
2819 "#endif\n"
2820 "\n"
2821 "#ifdef USEDEFERREDLIGHTMAP\n"
2822 "uniform half3 DeferredMod_Diffuse,\n"
2823 "uniform half3 DeferredMod_Specular,\n"
2824 "#endif\n"
2825 "uniform half3 Color_Ambient,\n"
2826 "uniform half3 Color_Diffuse,\n"
2827 "uniform half3 Color_Specular,\n"
2828 "uniform half SpecularPower,\n"
2829 "#ifdef USEGLOW\n"
2830 "uniform half3 Color_Glow,\n"
2831 "#endif\n"
2832 "uniform half Alpha,\n"
2833 "#ifdef USEREFLECTION\n"
2834 "uniform float4 DistortScaleRefractReflect,\n"
2835 "uniform float4 ScreenScaleRefractReflect,\n"
2836 "uniform float4 ScreenCenterRefractReflect,\n"
2837 "uniform half4 ReflectColor,\n"
2838 "#endif\n"
2839 "#ifdef MODE_LIGHTDIRECTION\n"
2840 "uniform half3 LightColor,\n"
2841 "#endif\n"
2842 "#ifdef MODE_LIGHTSOURCE\n"
2843 "uniform half3 LightColor,\n"
2844 "#endif\n"
2845 "\n"
2846 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2847 "uniform sampler2D Texture_Attenuation,\n"
2848 "uniform samplerCUBE Texture_Cube,\n"
2849 "\n"
2850 "#ifdef USESHADOWMAPRECT\n"
2851 "# ifdef USESHADOWSAMPLER\n"
2852 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2853 "# else\n"
2854 "uniform samplerRECT Texture_ShadowMapRect,\n"
2855 "# endif\n"
2856 "#endif\n"
2857 "\n"
2858 "#ifdef USESHADOWMAP2D\n"
2859 "# ifdef USESHADOWSAMPLER\n"
2860 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2861 "# else\n"
2862 "uniform sampler2D Texture_ShadowMap2D,\n"
2863 "# endif\n"
2864 "#endif\n"
2865 "\n"
2866 "#ifdef USESHADOWMAPVSDCT\n"
2867 "uniform samplerCUBE Texture_CubeProjection,\n"
2868 "#endif\n"
2869 "\n"
2870 "#ifdef USESHADOWMAPCUBE\n"
2871 "# ifdef USESHADOWSAMPLER\n"
2872 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2873 "# else\n"
2874 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2875 "# endif\n"
2876 "#endif\n"
2877 "\n"
2878 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2879 "uniform float2 ShadowMap_TextureScale,\n"
2880 "uniform float4 ShadowMap_Parameters,\n"
2881 "#endif\n"
2882 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2883 "\n"
2884 "out float4 gl_FragColor : COLOR\n"
2885 ")\n"
2886 "{\n"
2887 "       float2 TexCoord = TexCoordBoth.xy;\n"
2888 "#ifdef USEVERTEXTEXTUREBLEND\n"
2889 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
2890 "#endif\n"
2891 "#ifdef USEOFFSETMAPPING\n"
2892 "       // apply offsetmapping\n"
2893 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2894 "#define TexCoord TexCoordOffset\n"
2895 "#endif\n"
2896 "\n"
2897 "       // combine the diffuse textures (base, pants, shirt)\n"
2898 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
2899 "#ifdef USEALPHAKILL\n"
2900 "       if (color.a < 0.5)\n"
2901 "               discard;\n"
2902 "#endif\n"
2903 "       color.a *= Alpha;\n"
2904 "#ifdef USECOLORMAPPING\n"
2905 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord)) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
2906 "#endif\n"
2907 "#ifdef USEVERTEXTEXTUREBLEND\n"
2908 "       float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
2909 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
2910 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
2911 "       color.rgb = half3(mix(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
2912 "       color.a = 1.0;\n"
2913 "       //color = mix(half4(1, 0, 0, 1), color, terrainblend);\n"
2914 "#endif\n"
2915 "\n"
2916 "       // get the surface normal\n"
2917 "#ifdef USEVERTEXTEXTUREBLEND\n"
2918 "       half3 surfacenormal = normalize(half3(mix(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
2919 "#else\n"
2920 "       half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
2921 "#endif\n"
2922 "\n"
2923 "       // get the material colors\n"
2924 "       half3 diffusetex = color.rgb;\n"
2925 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2926 "# ifdef USEVERTEXTEXTUREBLEND\n"
2927 "       half3 glosstex = half3(mix(float3(tex2D(Texture_SecondaryGloss, TexCoord2)), float3(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
2928 "# else\n"
2929 "       half3 glosstex = half3(tex2D(Texture_Gloss, TexCoord));\n"
2930 "# endif\n"
2931 "#endif\n"
2932 "\n"
2933 "\n"
2934 "\n"
2935 "\n"
2936 "#ifdef MODE_LIGHTSOURCE\n"
2937 "       // light source\n"
2938 "       half3 lightnormal = half3(normalize(LightVector));\n"
2939 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2940 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
2941 "#ifdef USESPECULAR\n"
2942 "#ifdef USEEXACTSPECULARMATH\n"
2943 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
2944 "#else\n"
2945 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
2946 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
2947 "#endif\n"
2948 "       color.rgb += glosstex * (specular * Color_Specular);\n"
2949 "#endif\n"
2950 "       color.rgb *= LightColor;\n"
2951 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2952 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
2953 "       color.rgb *= ShadowMapCompare(CubeVector,\n"
2954 "# if defined(USESHADOWMAP2D)\n"
2955 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2956 "# endif\n"
2957 "# if defined(USESHADOWMAPRECT)\n"
2958 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2959 "# endif\n"
2960 "# if defined(USESHADOWMAPCUBE)\n"
2961 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2962 "# endif\n"
2963 "\n"
2964 "#ifdef USESHADOWMAPVSDCT\n"
2965 ", Texture_CubeProjection\n"
2966 "#endif\n"
2967 "       );\n"
2968 "\n"
2969 "#endif\n"
2970 "# ifdef USECUBEFILTER\n"
2971 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector));\n"
2972 "# endif\n"
2973 "#endif // MODE_LIGHTSOURCE\n"
2974 "\n"
2975 "\n"
2976 "\n"
2977 "\n"
2978 "#ifdef MODE_LIGHTDIRECTION\n"
2979 "#define SHADING\n"
2980 "       half3 lightnormal = half3(normalize(LightVector));\n"
2981 "#define lightcolor LightColor\n"
2982 "#endif // MODE_LIGHTDIRECTION\n"
2983 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2984 "#define SHADING\n"
2985 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
2986 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
2987 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
2988 "       // convert modelspace light vector to tangentspace\n"
2989 "       half3 lightnormal;\n"
2990 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
2991 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
2992 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
2993 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
2994 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
2995 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
2996 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
2997 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
2998 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
2999 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3000 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3001 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3002 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3003 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3004 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3005 "#define SHADING\n"
3006 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3007 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3008 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3009 "#endif\n"
3010 "\n"
3011 "\n"
3012 "\n"
3013 "\n"
3014 "#ifdef MODE_LIGHTMAP\n"
3015 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
3016 "#endif // MODE_LIGHTMAP\n"
3017 "#ifdef MODE_VERTEXCOLOR\n"
3018 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3019 "#endif // MODE_VERTEXCOLOR\n"
3020 "#ifdef MODE_FLATCOLOR\n"
3021 "       color.rgb = diffusetex * Color_Ambient;\n"
3022 "#endif // MODE_FLATCOLOR\n"
3023 "\n"
3024 "\n"
3025 "\n"
3026 "\n"
3027 "#ifdef SHADING\n"
3028 "# ifdef USEDIFFUSE\n"
3029 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3030 "#  ifdef USESPECULAR\n"
3031 "#   ifdef USEEXACTSPECULARMATH\n"
3032 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
3033 "#   else\n"
3034 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3035 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
3036 "#   endif\n"
3037 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
3038 "#  else\n"
3039 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3040 "#  endif\n"
3041 "# else\n"
3042 "       color.rgb = diffusetex * Color_Ambient;\n"
3043 "# endif\n"
3044 "#endif\n"
3045 "\n"
3046 "#ifdef USEDEFERREDLIGHTMAP\n"
3047 "       color.rgb += diffusetex * half3(texRECT(Texture_ScreenDiffuse, Pixel)) * DeferredMod_Diffuse;\n"
3048 "       color.rgb += glosstex * half3(texRECT(Texture_ScreenSpecular, Pixel)) * DeferredMod_Specular;\n"
3049 "       color.rgb = half3(texRECT(Texture_ScreenDepth, Pixel));\n"
3050 "#endif\n"
3051 "\n"
3052 "#ifdef USEGLOW\n"
3053 "#ifdef USEVERTEXTEXTUREBLEND\n"
3054 "       color.rgb += mix(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
3055 "#else\n"
3056 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
3057 "#endif\n"
3058 "#endif\n"
3059 "\n"
3060 "#ifdef USEFOG\n"
3061 "#ifdef MODE_LIGHTSOURCE\n"
3062 "       color.rgb *= half(FogVertex());\n"
3063 "#else\n"
3064 "       color.rgb = mix(FogColor, float3(color.rgb), FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3065 "#endif\n"
3066 "#endif\n"
3067 "\n"
3068 "       // 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"
3069 "#ifdef USEREFLECTION\n"
3070 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3071 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3072 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3073 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
3074 "       // FIXME temporary hack to detect the case that the reflection\n"
3075 "       // gets blackened at edges due to leaving the area that contains actual\n"
3076 "       // content.\n"
3077 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3078 "       // 'appening.\n"
3079 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3080 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3081 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3082 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3083 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3084 "       color.rgb = mix(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
3085 "#endif\n"
3086 "\n"
3087 "       gl_FragColor = float4(color);\n"
3088 "}\n"
3089 "#endif // FRAGMENT_SHADER\n"
3090 "\n"
3091 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3092 "#endif // !MODE_DEFERREDGEOMETRY\n"
3093 "#endif // !MODE_WATER\n"
3094 "#endif // !MODE_REFRACTION\n"
3095 "#endif // !MODE_BLOOMBLUR\n"
3096 "#endif // !MODE_GENERIC\n"
3097 "#endif // !MODE_POSTPROCESS\n"
3098 "#endif // !MODE_SHOWDEPTH\n"
3099 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3100 ;
3101
3102 //=======================================================================================================================================================
3103
3104 typedef struct shaderpermutationinfo_s
3105 {
3106         const char *pretext;
3107         const char *name;
3108 }
3109 shaderpermutationinfo_t;
3110
3111 typedef struct shadermodeinfo_s
3112 {
3113         const char *vertexfilename;
3114         const char *geometryfilename;
3115         const char *fragmentfilename;
3116         const char *pretext;
3117         const char *name;
3118 }
3119 shadermodeinfo_t;
3120
3121 typedef enum shaderpermutation_e
3122 {
3123         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3124         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3125         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3126         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3127         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3128         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3129         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3130         SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
3131         SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
3132         SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
3133         SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
3134         SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
3135         SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
3136         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3137         SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3138         SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3139         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3140         SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
3141         SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
3142         SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
3143         SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
3144         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3145         SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
3146         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3147         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3148         SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3149         SHADERPERMUTATION_LIMIT = 1<<26, ///< size of permutations array
3150         SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
3151 }
3152 shaderpermutation_t;
3153
3154 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3155 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3156 {
3157         {"#define USEDIFFUSE\n", " diffuse"},
3158         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3159         {"#define USEVIEWTINT\n", " viewtint"},
3160         {"#define USECOLORMAPPING\n", " colormapping"},
3161         {"#define USESATURATION\n", " saturation"},
3162         {"#define USEFOGINSIDE\n", " foginside"},
3163         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3164         {"#define USEGAMMARAMPS\n", " gammaramps"},
3165         {"#define USECUBEFILTER\n", " cubefilter"},
3166         {"#define USEGLOW\n", " glow"},
3167         {"#define USEBLOOM\n", " bloom"},
3168         {"#define USESPECULAR\n", " specular"},
3169         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3170         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3171         {"#define USEREFLECTION\n", " reflection"},
3172         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3173         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3174         {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3175         {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3176         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3177         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3178         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3179         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3180         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3181         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3182         {"#define USEALPHAKILL\n", " alphakill"},
3183 };
3184
3185 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3186 typedef enum shadermode_e
3187 {
3188         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3189         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3190         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3191         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3192         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3193         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3194         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3195         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3196         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3197         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3198         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3199         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3200         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3201         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3202         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3203         SHADERMODE_COUNT
3204 }
3205 shadermode_t;
3206
3207 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3208 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3209 {
3210         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3211         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3212         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3213         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3214         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3215         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3216         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3217         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3218         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3219         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3220         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3221         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3222         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3223         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3224         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3225 };
3226
3227 #ifdef SUPPORTCG
3228 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3229 {
3230         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3231         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3232         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3233         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3234         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3235         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3236         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3237         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3238         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3239         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3240         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3241         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3242         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3243         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3244         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3245 };
3246 #endif
3247
3248 struct r_glsl_permutation_s;
3249 typedef struct r_glsl_permutation_s
3250 {
3251         /// hash lookup data
3252         struct r_glsl_permutation_s *hashnext;
3253         unsigned int mode;
3254         unsigned int permutation;
3255
3256         /// indicates if we have tried compiling this permutation already
3257         qboolean compiled;
3258         /// 0 if compilation failed
3259         int program;
3260         /// locations of detected uniforms in program object, or -1 if not found
3261         int loc_Texture_First;
3262         int loc_Texture_Second;
3263         int loc_Texture_GammaRamps;
3264         int loc_Texture_Normal;
3265         int loc_Texture_Color;
3266         int loc_Texture_Gloss;
3267         int loc_Texture_Glow;
3268         int loc_Texture_SecondaryNormal;
3269         int loc_Texture_SecondaryColor;
3270         int loc_Texture_SecondaryGloss;
3271         int loc_Texture_SecondaryGlow;
3272         int loc_Texture_Pants;
3273         int loc_Texture_Shirt;
3274         int loc_Texture_FogMask;
3275         int loc_Texture_Lightmap;
3276         int loc_Texture_Deluxemap;
3277         int loc_Texture_Attenuation;
3278         int loc_Texture_Cube;
3279         int loc_Texture_Refraction;
3280         int loc_Texture_Reflection;
3281         int loc_Texture_ShadowMapRect;
3282         int loc_Texture_ShadowMapCube;
3283         int loc_Texture_ShadowMap2D;
3284         int loc_Texture_CubeProjection;
3285         int loc_Texture_ScreenDepth;
3286         int loc_Texture_ScreenNormalMap;
3287         int loc_Texture_ScreenDiffuse;
3288         int loc_Texture_ScreenSpecular;
3289         int loc_Alpha;
3290         int loc_BloomBlur_Parameters;
3291         int loc_ClientTime;
3292         int loc_Color_Ambient;
3293         int loc_Color_Diffuse;
3294         int loc_Color_Specular;
3295         int loc_Color_Glow;
3296         int loc_Color_Pants;
3297         int loc_Color_Shirt;
3298         int loc_DeferredColor_Ambient;
3299         int loc_DeferredColor_Diffuse;
3300         int loc_DeferredColor_Specular;
3301         int loc_DeferredMod_Diffuse;
3302         int loc_DeferredMod_Specular;
3303         int loc_DistortScaleRefractReflect;
3304         int loc_EyePosition;
3305         int loc_FogColor;
3306         int loc_FogHeightFade;
3307         int loc_FogPlane;
3308         int loc_FogPlaneViewDist;
3309         int loc_FogRangeRecip;
3310         int loc_LightColor;
3311         int loc_LightDir;
3312         int loc_LightPosition;
3313         int loc_OffsetMapping_Scale;
3314         int loc_PixelSize;
3315         int loc_ReflectColor;
3316         int loc_ReflectFactor;
3317         int loc_ReflectOffset;
3318         int loc_RefractColor;
3319         int loc_Saturation;
3320         int loc_ScreenCenterRefractReflect;
3321         int loc_ScreenScaleRefractReflect;
3322         int loc_ScreenToDepth;
3323         int loc_ShadowMap_Parameters;
3324         int loc_ShadowMap_TextureScale;
3325         int loc_SpecularPower;
3326         int loc_UserVec1;
3327         int loc_UserVec2;
3328         int loc_UserVec3;
3329         int loc_UserVec4;
3330         int loc_ViewTintColor;
3331         int loc_ViewToLight;
3332         int loc_ModelToLight;
3333         int loc_TexMatrix;
3334         int loc_BackgroundTexMatrix;
3335         int loc_ModelViewProjectionMatrix;
3336         int loc_ModelViewMatrix;
3337 }
3338 r_glsl_permutation_t;
3339
3340 #define SHADERPERMUTATION_HASHSIZE 256
3341
3342 /// information about each possible shader permutation
3343 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3344 /// currently selected permutation
3345 r_glsl_permutation_t *r_glsl_permutation;
3346 /// storage for permutations linked in the hash table
3347 memexpandablearray_t r_glsl_permutationarray;
3348
3349 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3350 {
3351         //unsigned int hashdepth = 0;
3352         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3353         r_glsl_permutation_t *p;
3354         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3355         {
3356                 if (p->mode == mode && p->permutation == permutation)
3357                 {
3358                         //if (hashdepth > 10)
3359                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3360                         return p;
3361                 }
3362                 //hashdepth++;
3363         }
3364         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3365         p->mode = mode;
3366         p->permutation = permutation;
3367         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3368         r_glsl_permutationhash[mode][hashindex] = p;
3369         //if (hashdepth > 10)
3370         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3371         return p;
3372 }
3373
3374 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3375 {
3376         char *shaderstring;
3377         if (!filename || !filename[0])
3378                 return NULL;
3379         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3380         if (shaderstring)
3381         {
3382                 if (printfromdisknotice)
3383                         Con_DPrintf("from disk %s... ", filename);
3384                 return shaderstring;
3385         }
3386         else if (!strcmp(filename, "glsl/default.glsl"))
3387         {
3388                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
3389                 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
3390         }
3391         return shaderstring;
3392 }
3393
3394 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3395 {
3396         int i;
3397         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3398         int vertstrings_count = 0;
3399         int geomstrings_count = 0;
3400         int fragstrings_count = 0;
3401         char *vertexstring, *geometrystring, *fragmentstring;
3402         const char *vertstrings_list[32+3];
3403         const char *geomstrings_list[32+3];
3404         const char *fragstrings_list[32+3];
3405         char permutationname[256];
3406
3407         if (p->compiled)
3408                 return;
3409         p->compiled = true;
3410         p->program = 0;
3411
3412         permutationname[0] = 0;
3413         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3414         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3415         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3416
3417         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3418
3419         // the first pretext is which type of shader to compile as
3420         // (later these will all be bound together as a program object)
3421         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3422         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3423         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3424
3425         // the second pretext is the mode (for example a light source)
3426         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3427         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3428         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3429         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3430
3431         // now add all the permutation pretexts
3432         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3433         {
3434                 if (permutation & (1<<i))
3435                 {
3436                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3437                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3438                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3439                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3440                 }
3441                 else
3442                 {
3443                         // keep line numbers correct
3444                         vertstrings_list[vertstrings_count++] = "\n";
3445                         geomstrings_list[geomstrings_count++] = "\n";
3446                         fragstrings_list[fragstrings_count++] = "\n";
3447                 }
3448         }
3449
3450         // now append the shader text itself
3451         vertstrings_list[vertstrings_count++] = vertexstring;
3452         geomstrings_list[geomstrings_count++] = geometrystring;
3453         fragstrings_list[fragstrings_count++] = fragmentstring;
3454
3455         // if any sources were NULL, clear the respective list
3456         if (!vertexstring)
3457                 vertstrings_count = 0;
3458         if (!geometrystring)
3459                 geomstrings_count = 0;
3460         if (!fragmentstring)
3461                 fragstrings_count = 0;
3462
3463         // compile the shader program
3464         if (vertstrings_count + geomstrings_count + fragstrings_count)
3465                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3466         if (p->program)
3467         {
3468                 CHECKGLERROR
3469                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3470                 // look up all the uniform variable names we care about, so we don't
3471                 // have to look them up every time we set them
3472
3473                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3474                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3475                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3476                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3477                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3478                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3479                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3480                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3481                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3482                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3483                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3484                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3485                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3486                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3487                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3488                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3489                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3490                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3491                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3492                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3493                 p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3494                 p->loc_Texture_ShadowMapCube      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3495                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3496                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3497                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3498                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3499                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3500                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3501                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3502                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3503                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3504                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3505                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3506                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3507                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3508                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3509                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3510                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3511                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3512                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3513                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3514                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3515                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3516                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3517                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3518                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3519                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3520                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3521                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3522                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3523                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3524                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3525                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3526                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3527                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3528                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3529                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3530                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3531                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3532                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3533                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3534                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3535                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3536                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3537                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3538                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3539                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3540                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3541                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3542                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3543                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3544                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3545                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3546                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3547                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3548                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3549                 // initialize the samplers to refer to the texture units we use
3550                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3551                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3552                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3553                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3554                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3555                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3556                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3557                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3558                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3559                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3560                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3561                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3562                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3563                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3564                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3565                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3566                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3567                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3568                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3569                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3570                 if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , GL20TU_SHADOWMAPRECT);
3571                 if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
3572                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
3573                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3574                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3575                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3576                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3577                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3578                 CHECKGLERROR
3579                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3580         }
3581         else
3582                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3583
3584         // free the strings
3585         if (vertexstring)
3586                 Mem_Free(vertexstring);
3587         if (geometrystring)
3588                 Mem_Free(geometrystring);
3589         if (fragmentstring)
3590                 Mem_Free(fragmentstring);
3591 }
3592
3593 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3594 {
3595         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3596         if (r_glsl_permutation != perm)
3597         {
3598                 r_glsl_permutation = perm;
3599                 if (!r_glsl_permutation->program)
3600                 {
3601                         if (!r_glsl_permutation->compiled)
3602                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3603                         if (!r_glsl_permutation->program)
3604                         {
3605                                 // remove features until we find a valid permutation
3606                                 int i;
3607                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3608                                 {
3609                                         // reduce i more quickly whenever it would not remove any bits
3610                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3611                                         if (!(permutation & j))
3612                                                 continue;
3613                                         permutation -= j;
3614                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3615                                         if (!r_glsl_permutation->compiled)
3616                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3617                                         if (r_glsl_permutation->program)
3618                                                 break;
3619                                 }
3620                                 if (i >= SHADERPERMUTATION_COUNT)
3621                                 {
3622                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3623                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3624                                         qglUseProgramObjectARB(0);CHECKGLERROR
3625                                         return; // no bit left to clear, entire mode is broken
3626                                 }
3627                         }
3628                 }
3629                 CHECKGLERROR
3630                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3631         }
3632         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3633         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3634 }
3635
3636 #ifdef SUPPORTCG
3637 #include <Cg/cgGL.h>
3638 struct r_cg_permutation_s;
3639 typedef struct r_cg_permutation_s
3640 {
3641         /// hash lookup data
3642         struct r_cg_permutation_s *hashnext;
3643         unsigned int mode;
3644         unsigned int permutation;
3645
3646         /// indicates if we have tried compiling this permutation already
3647         qboolean compiled;
3648         /// 0 if compilation failed
3649         CGprogram vprogram;
3650         CGprogram fprogram;
3651         /// locations of detected parameters in programs, or NULL if not found
3652         CGparameter vp_EyePosition;
3653         CGparameter vp_FogPlane;
3654         CGparameter vp_LightDir;
3655         CGparameter vp_LightPosition;
3656         CGparameter vp_ModelToLight;
3657         CGparameter vp_TexMatrix;
3658         CGparameter vp_BackgroundTexMatrix;
3659         CGparameter vp_ModelViewProjectionMatrix;
3660         CGparameter vp_ModelViewMatrix;
3661
3662         CGparameter fp_Texture_First;
3663         CGparameter fp_Texture_Second;
3664         CGparameter fp_Texture_GammaRamps;
3665         CGparameter fp_Texture_Normal;
3666         CGparameter fp_Texture_Color;
3667         CGparameter fp_Texture_Gloss;
3668         CGparameter fp_Texture_Glow;
3669         CGparameter fp_Texture_SecondaryNormal;
3670         CGparameter fp_Texture_SecondaryColor;
3671         CGparameter fp_Texture_SecondaryGloss;
3672         CGparameter fp_Texture_SecondaryGlow;
3673         CGparameter fp_Texture_Pants;
3674         CGparameter fp_Texture_Shirt;
3675         CGparameter fp_Texture_FogMask;
3676         CGparameter fp_Texture_Lightmap;
3677         CGparameter fp_Texture_Deluxemap;
3678         CGparameter fp_Texture_Attenuation;
3679         CGparameter fp_Texture_Cube;
3680         CGparameter fp_Texture_Refraction;
3681         CGparameter fp_Texture_Reflection;
3682         CGparameter fp_Texture_ShadowMapRect;
3683         CGparameter fp_Texture_ShadowMapCube;
3684         CGparameter fp_Texture_ShadowMap2D;
3685         CGparameter fp_Texture_CubeProjection;
3686         CGparameter fp_Texture_ScreenDepth;
3687         CGparameter fp_Texture_ScreenNormalMap;
3688         CGparameter fp_Texture_ScreenDiffuse;
3689         CGparameter fp_Texture_ScreenSpecular;
3690         CGparameter fp_Alpha;
3691         CGparameter fp_BloomBlur_Parameters;
3692         CGparameter fp_ClientTime;
3693         CGparameter fp_Color_Ambient;
3694         CGparameter fp_Color_Diffuse;
3695         CGparameter fp_Color_Specular;
3696         CGparameter fp_Color_Glow;
3697         CGparameter fp_Color_Pants;
3698         CGparameter fp_Color_Shirt;
3699         CGparameter fp_DeferredColor_Ambient;
3700         CGparameter fp_DeferredColor_Diffuse;
3701         CGparameter fp_DeferredColor_Specular;
3702         CGparameter fp_DeferredMod_Diffuse;
3703         CGparameter fp_DeferredMod_Specular;
3704         CGparameter fp_DistortScaleRefractReflect;
3705         CGparameter fp_EyePosition;
3706         CGparameter fp_FogColor;
3707         CGparameter fp_FogHeightFade;
3708         CGparameter fp_FogPlane;
3709         CGparameter fp_FogPlaneViewDist;
3710         CGparameter fp_FogRangeRecip;
3711         CGparameter fp_LightColor;
3712         CGparameter fp_LightDir;
3713         CGparameter fp_LightPosition;
3714         CGparameter fp_OffsetMapping_Scale;
3715         CGparameter fp_PixelSize;
3716         CGparameter fp_ReflectColor;
3717         CGparameter fp_ReflectFactor;
3718         CGparameter fp_ReflectOffset;
3719         CGparameter fp_RefractColor;
3720         CGparameter fp_Saturation;
3721         CGparameter fp_ScreenCenterRefractReflect;
3722         CGparameter fp_ScreenScaleRefractReflect;
3723         CGparameter fp_ScreenToDepth;
3724         CGparameter fp_ShadowMap_Parameters;
3725         CGparameter fp_ShadowMap_TextureScale;
3726         CGparameter fp_SpecularPower;
3727         CGparameter fp_UserVec1;
3728         CGparameter fp_UserVec2;
3729         CGparameter fp_UserVec3;
3730         CGparameter fp_UserVec4;
3731         CGparameter fp_ViewTintColor;
3732         CGparameter fp_ViewToLight;
3733 }
3734 r_cg_permutation_t;
3735
3736 /// information about each possible shader permutation
3737 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3738 /// currently selected permutation
3739 r_cg_permutation_t *r_cg_permutation;
3740 /// storage for permutations linked in the hash table
3741 memexpandablearray_t r_cg_permutationarray;
3742
3743 #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));}}
3744
3745 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3746 {
3747         //unsigned int hashdepth = 0;
3748         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3749         r_cg_permutation_t *p;
3750         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3751         {
3752                 if (p->mode == mode && p->permutation == permutation)
3753                 {
3754                         //if (hashdepth > 10)
3755                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3756                         return p;
3757                 }
3758                 //hashdepth++;
3759         }
3760         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3761         p->mode = mode;
3762         p->permutation = permutation;
3763         p->hashnext = r_cg_permutationhash[mode][hashindex];
3764         r_cg_permutationhash[mode][hashindex] = p;
3765         //if (hashdepth > 10)
3766         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3767         return p;
3768 }
3769
3770 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3771 {
3772         char *shaderstring;
3773         if (!filename || !filename[0])
3774                 return NULL;
3775         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3776         if (shaderstring)
3777         {
3778                 if (printfromdisknotice)
3779                         Con_DPrintf("from disk %s... ", filename);
3780                 return shaderstring;
3781         }
3782         else if (!strcmp(filename, "cg/default.cg"))
3783         {
3784                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtincgshaderstring) + 1);
3785                 memcpy(shaderstring, builtincgshaderstring, strlen(builtincgshaderstring) + 1);
3786         }
3787         return shaderstring;
3788 }
3789
3790 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
3791 {
3792         int i;
3793         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
3794         int vertstrings_count = 0, vertstring_length = 0;
3795         int geomstrings_count = 0, geomstring_length = 0;
3796         int fragstrings_count = 0, fragstring_length = 0;
3797         char *t;
3798         char *vertexstring, *geometrystring, *fragmentstring;
3799         char *vertstring, *geomstring, *fragstring;
3800         const char *vertstrings_list[32+3];
3801         const char *geomstrings_list[32+3];
3802         const char *fragstrings_list[32+3];
3803         char permutationname[256];
3804         CGprofile vertexProfile;
3805         CGprofile fragmentProfile;
3806
3807         if (p->compiled)
3808                 return;
3809         p->compiled = true;
3810         p->vprogram = NULL;
3811         p->fprogram = NULL;
3812
3813         permutationname[0] = 0;
3814         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
3815         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
3816         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
3817
3818         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3819
3820         // the first pretext is which type of shader to compile as
3821         // (later these will all be bound together as a program object)
3822         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3823         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3824         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3825
3826         // the second pretext is the mode (for example a light source)
3827         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3828         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3829         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3830         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3831
3832         // now add all the permutation pretexts
3833         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3834         {
3835                 if (permutation & (1<<i))
3836                 {
3837                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3838                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3839                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3840                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3841                 }
3842                 else
3843                 {
3844                         // keep line numbers correct
3845                         vertstrings_list[vertstrings_count++] = "\n";
3846                         geomstrings_list[geomstrings_count++] = "\n";
3847                         fragstrings_list[fragstrings_count++] = "\n";
3848                 }
3849         }
3850
3851         // now append the shader text itself
3852         vertstrings_list[vertstrings_count++] = vertexstring;
3853         geomstrings_list[geomstrings_count++] = geometrystring;
3854         fragstrings_list[fragstrings_count++] = fragmentstring;
3855
3856         // if any sources were NULL, clear the respective list
3857         if (!vertexstring)
3858                 vertstrings_count = 0;
3859         if (!geometrystring)
3860                 geomstrings_count = 0;
3861         if (!fragmentstring)
3862                 fragstrings_count = 0;
3863
3864         vertstring_length = 0;
3865         for (i = 0;i < vertstrings_count;i++)
3866                 vertstring_length += strlen(vertstrings_list[i]);
3867         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
3868         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
3869                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
3870
3871         geomstring_length = 0;
3872         for (i = 0;i < geomstrings_count;i++)
3873                 geomstring_length += strlen(geomstrings_list[i]);
3874         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
3875         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
3876                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
3877
3878         fragstring_length = 0;
3879         for (i = 0;i < fragstrings_count;i++)
3880                 fragstring_length += strlen(fragstrings_list[i]);
3881         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
3882         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
3883                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
3884
3885         CHECKGLERROR
3886         CHECKCGERROR
3887         //vertexProfile = CG_PROFILE_ARBVP1;
3888         //fragmentProfile = CG_PROFILE_ARBFP1;
3889         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
3890         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
3891         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
3892         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
3893         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
3894         CHECKGLERROR
3895
3896         // compile the vertex program
3897         if (vertstring[0] && (p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, CG_PROFILE_ARBVP1, NULL, NULL)))
3898         {
3899                 CHECKCGERROR
3900                 cgCompileProgram(p->vprogram);CHECKCGERROR
3901                 if (!cgIsProgramCompiled(p->vprogram))
3902                 {
3903                         CHECKCGERROR
3904                         cgDestroyProgram(p->vprogram);CHECKCGERROR
3905                         p->vprogram = 0;
3906                 }
3907                 else
3908                 {
3909                         cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
3910                         cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
3911                         // look up all the uniform variable names we care about, so we don't
3912                         // have to look them up every time we set them
3913                         CHECKCGERROR
3914                         p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
3915                         p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
3916                         p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
3917                         p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
3918                         p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
3919                         p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
3920                         p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
3921                         p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
3922                         p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
3923                         CHECKCGERROR
3924                 }
3925         }
3926
3927         // compile the fragment program
3928         if (fragstring[0] && (p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, CG_PROFILE_ARBFP1, NULL, NULL)))
3929         {
3930                 cgCompileProgram(p->fprogram);CHECKCGERROR
3931                 if (!cgIsProgramCompiled(p->fprogram))
3932                 {
3933                         CHECKCGERROR
3934                         cgDestroyProgram(p->fprogram);CHECKCGERROR
3935                         p->fprogram = 0;
3936                 }
3937                 else
3938                 {
3939                         cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
3940                         cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
3941                         CHECKCGERROR
3942                         p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
3943                         p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
3944                         p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
3945                         p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
3946                         p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
3947                         p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
3948                         p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
3949                         p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
3950                         p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
3951                         p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
3952                         p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
3953                         p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
3954                         p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
3955                         p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
3956                         p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
3957                         p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
3958                         p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
3959                         p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
3960                         p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
3961                         p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
3962                         p->fp_Texture_ShadowMapRect      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
3963                         p->fp_Texture_ShadowMapCube      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
3964                         p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
3965                         p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
3966                         p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
3967                         p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
3968                         p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
3969                         p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
3970                         p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
3971                         p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
3972                         p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
3973                         p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
3974                         p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
3975                         p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
3976                         p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
3977                         p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
3978                         p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
3979                         p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
3980                         p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
3981                         p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
3982                         p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
3983                         p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
3984                         p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
3985                         p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
3986                         p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
3987                         p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
3988                         p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
3989                         p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
3990                         p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
3991                         p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
3992                         p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
3993                         p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
3994                         p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
3995                         p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
3996                         p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
3997                         p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
3998                         p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
3999                         p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4000                         p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4001                         p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4002                         p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4003                         p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4004                         p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4005                         p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4006                         p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4007                         p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4008                         p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4009                         p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4010                         p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4011                         p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4012                         p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4013                         CHECKCGERROR
4014                 }
4015         }
4016
4017         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4018                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4019         else
4020                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4021
4022         // free the strings
4023         if (vertstring)
4024                 Mem_Free(vertstring);
4025         if (geomstring)
4026                 Mem_Free(geomstring);
4027         if (fragstring)
4028                 Mem_Free(fragstring);
4029         if (vertexstring)
4030                 Mem_Free(vertexstring);
4031         if (geometrystring)
4032                 Mem_Free(geometrystring);
4033         if (fragmentstring)
4034                 Mem_Free(fragmentstring);
4035 }
4036
4037 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4038 {
4039         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4040         CHECKGLERROR
4041         CHECKCGERROR
4042         if (r_cg_permutation != perm)
4043         {
4044                 r_cg_permutation = perm;
4045                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4046                 {
4047                         if (!r_cg_permutation->compiled)
4048                                 R_CG_CompilePermutation(perm, mode, permutation);
4049                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4050                         {
4051                                 // remove features until we find a valid permutation
4052                                 int i;
4053                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4054                                 {
4055                                         // reduce i more quickly whenever it would not remove any bits
4056                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4057                                         if (!(permutation & j))
4058                                                 continue;
4059                                         permutation -= j;
4060                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4061                                         if (!r_cg_permutation->compiled)
4062                                                 R_CG_CompilePermutation(perm, mode, permutation);
4063                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4064                                                 break;
4065                                 }
4066                                 if (i >= SHADERPERMUTATION_COUNT)
4067                                 {
4068                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4069                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4070                                         return; // no bit left to clear, entire mode is broken
4071                                 }
4072                         }
4073                 }
4074                 CHECKGLERROR
4075                 CHECKCGERROR
4076                 if (r_cg_permutation->vprogram)
4077                 {
4078                         //cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4079                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4080                         //cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4081                 }
4082                 else
4083                 {
4084                         //cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4085                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4086                 }
4087                 if (r_cg_permutation->fprogram)
4088                 {
4089                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4090                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4091                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4092                 }
4093                 else
4094                 {
4095                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4096                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4097                 }
4098         }
4099         CHECKCGERROR
4100         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4101         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4102 }
4103
4104 void CG_BindTexture(CGparameter param, int texnum)
4105 {
4106         cgGLSetTextureParameter(param, texnum);
4107         cgGLEnableTextureParameter(param);
4108 }
4109 #endif
4110
4111 void R_GLSL_Restart_f(void)
4112 {
4113         unsigned int i, limit;
4114         switch(vid.renderpath)
4115         {
4116         case RENDERPATH_GL20:
4117                 {
4118                         r_glsl_permutation_t *p;
4119                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4120                         for (i = 0;i < limit;i++)
4121                         {
4122                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4123                                 {
4124                                         GL_Backend_FreeProgram(p->program);
4125                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4126                                 }
4127                         }
4128                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4129                 }
4130                 break;
4131         case RENDERPATH_CGGL:
4132 #ifdef SUPPORTCG
4133                 {
4134                         r_cg_permutation_t *p;
4135                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4136                         for (i = 0;i < limit;i++)
4137                         {
4138                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4139                                 {
4140                                         if (p->vprogram)
4141                                                 cgDestroyProgram(p->vprogram);
4142                                         if (p->fprogram)
4143                                                 cgDestroyProgram(p->fprogram);
4144                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4145                                 }
4146                         }
4147                 }
4148                 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4149                 break;
4150 #endif
4151         case RENDERPATH_GL13:
4152         case RENDERPATH_GL11:
4153                 break;
4154         }
4155 }
4156
4157 void R_GLSL_DumpShader_f(void)
4158 {
4159         int i;
4160         qfile_t *file;
4161
4162         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4163         if (file)
4164         {
4165                 FS_Print(file, "/* The engine may define the following macros:\n");
4166                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4167                 for (i = 0;i < SHADERMODE_COUNT;i++)
4168                         FS_Print(file, glslshadermodeinfo[i].pretext);
4169                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4170                         FS_Print(file, shaderpermutationinfo[i].pretext);
4171                 FS_Print(file, "*/\n");
4172                 FS_Print(file, builtinshaderstring);
4173                 FS_Close(file);
4174                 Con_Printf("glsl/default.glsl written\n");
4175         }
4176         else
4177                 Con_Printf("failed to write to glsl/default.glsl\n");
4178
4179 #ifdef SUPPORTCG
4180         file = FS_OpenRealFile("cg/default.cg", "w", false);
4181         if (file)
4182         {
4183                 FS_Print(file, "/* The engine may define the following macros:\n");
4184                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4185                 for (i = 0;i < SHADERMODE_COUNT;i++)
4186                         FS_Print(file, cgshadermodeinfo[i].pretext);
4187                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4188                         FS_Print(file, shaderpermutationinfo[i].pretext);
4189                 FS_Print(file, "*/\n");
4190                 FS_Print(file, builtincgshaderstring);
4191                 FS_Close(file);
4192                 Con_Printf("cg/default.cg written\n");
4193         }
4194         else
4195                 Con_Printf("failed to write to cg/default.cg\n");
4196 #endif
4197 }
4198
4199 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4200 {
4201         if (!second)
4202                 texturemode = GL_MODULATE;
4203         switch (vid.renderpath)
4204         {
4205         case RENDERPATH_GL20:
4206                 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))));
4207                 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
4208                 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, second);
4209                 break;
4210         case RENDERPATH_CGGL:
4211 #ifdef SUPPORTCG
4212                 CHECKCGERROR
4213                 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))));
4214                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4215                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4216 #endif
4217                 break;
4218         case RENDERPATH_GL13:
4219                 R_Mesh_TexBind(0, first );
4220                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4221                 R_Mesh_TexBind(1, second);
4222                 if (second)
4223                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4224                 break;
4225         case RENDERPATH_GL11:
4226                 R_Mesh_TexBind(0, first );
4227                 break;
4228         }
4229 }
4230
4231 void R_SetupShader_DepthOrShadow(void)
4232 {
4233         switch (vid.renderpath)
4234         {
4235         case RENDERPATH_GL20:
4236                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4237                 break;
4238         case RENDERPATH_CGGL:
4239 #ifdef SUPPORTCG
4240                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4241 #endif
4242                 break;
4243         case RENDERPATH_GL13:
4244                 R_Mesh_TexBind(0, 0);
4245                 R_Mesh_TexBind(1, 0);
4246                 break;
4247         case RENDERPATH_GL11:
4248                 R_Mesh_TexBind(0, 0);
4249                 break;
4250         }
4251 }
4252
4253 void R_SetupShader_ShowDepth(void)
4254 {
4255         switch (vid.renderpath)
4256         {
4257         case RENDERPATH_GL20:
4258                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4259                 break;
4260         case RENDERPATH_CGGL:
4261 #ifdef SUPPORTCG
4262                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4263 #endif
4264                 break;
4265         case RENDERPATH_GL13:
4266                 break;
4267         case RENDERPATH_GL11:
4268                 break;
4269         }
4270 }
4271
4272 extern qboolean r_shadow_usingdeferredprepass;
4273 extern cvar_t r_shadow_deferred_8bitrange;
4274 extern rtexture_t *r_shadow_attenuationgradienttexture;
4275 extern rtexture_t *r_shadow_attenuation2dtexture;
4276 extern rtexture_t *r_shadow_attenuation3dtexture;
4277 extern qboolean r_shadow_usingshadowmaprect;
4278 extern qboolean r_shadow_usingshadowmapcube;
4279 extern qboolean r_shadow_usingshadowmap2d;
4280 extern float r_shadow_shadowmap_texturescale[2];
4281 extern float r_shadow_shadowmap_parameters[4];
4282 extern qboolean r_shadow_shadowmapvsdct;
4283 extern qboolean r_shadow_shadowmapsampler;
4284 extern int r_shadow_shadowmappcf;
4285 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4286 extern rtexture_t *r_shadow_shadowmap2dtexture;
4287 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4288 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4289 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4290 extern int r_shadow_prepass_width;
4291 extern int r_shadow_prepass_height;
4292 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4293 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4294 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4295 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4296 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
4297 {
4298         // select a permutation of the lighting shader appropriate to this
4299         // combination of texture, entity, light source, and fogging, only use the
4300         // minimum features necessary to avoid wasting rendering time in the
4301         // fragment shader on features that are not being used
4302         unsigned int permutation = 0;
4303         unsigned int mode = 0;
4304         float m16f[16];
4305         // TODO: implement geometry-shader based shadow volumes someday
4306         if (r_glsl_offsetmapping.integer)
4307         {
4308                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4309                 if (r_glsl_offsetmapping_reliefmapping.integer)
4310                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4311         }
4312         if (rsurfacepass == RSURFPASS_BACKGROUND)
4313         {
4314                 // distorted background
4315                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4316                         mode = SHADERMODE_WATER;
4317                 else
4318                         mode = SHADERMODE_REFRACTION;
4319         }
4320         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4321         {
4322                 // normalmap (deferred prepass), may use alpha test on diffuse
4323                 mode = SHADERMODE_DEFERREDGEOMETRY;
4324                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4325                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4326                 if (r_glsl_offsetmapping.integer)
4327                 {
4328                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4329                         if (r_glsl_offsetmapping_reliefmapping.integer)
4330                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4331                 }
4332         }
4333         else if (rsurfacepass == RSURFPASS_RTLIGHT)
4334         {
4335                 // light source
4336                 mode = SHADERMODE_LIGHTSOURCE;
4337                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4338                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4339                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4340                         permutation |= SHADERPERMUTATION_CUBEFILTER;
4341                 if (diffusescale > 0)
4342                         permutation |= SHADERPERMUTATION_DIFFUSE;
4343                 if (specularscale > 0)
4344                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4345                 if (r_refdef.fogenabled)
4346                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4347                 if (rsurface.texture->colormapping)
4348                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4349                 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4350                 {
4351                         if (r_shadow_usingshadowmaprect)
4352                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4353                         if (r_shadow_usingshadowmap2d)
4354                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4355                         if (r_shadow_usingshadowmapcube)
4356                                 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4357                         else if(r_shadow_shadowmapvsdct)
4358                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4359
4360                         if (r_shadow_shadowmapsampler)
4361                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4362                         if (r_shadow_shadowmappcf > 1)
4363                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4364                         else if (r_shadow_shadowmappcf)
4365                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4366                 }
4367         }
4368         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4369         {
4370                 // unshaded geometry (fullbright or ambient model lighting)
4371                 mode = SHADERMODE_FLATCOLOR;
4372                 ambientscale = diffusescale = specularscale = 0;
4373                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4374                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4375                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4376                         permutation |= SHADERPERMUTATION_GLOW;
4377                 if (r_refdef.fogenabled)
4378                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4379                 if (rsurface.texture->colormapping)
4380                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4381                 if (r_glsl_offsetmapping.integer)
4382                 {
4383                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4384                         if (r_glsl_offsetmapping_reliefmapping.integer)
4385                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4386                 }
4387                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4388                         permutation |= SHADERPERMUTATION_REFLECTION;
4389         }
4390         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4391         {
4392                 // directional model lighting
4393                 mode = SHADERMODE_LIGHTDIRECTION;
4394                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4395                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4396                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4397                         permutation |= SHADERPERMUTATION_GLOW;
4398                 permutation |= SHADERPERMUTATION_DIFFUSE;
4399                 if (specularscale > 0)
4400                         permutation |= SHADERPERMUTATION_SPECULAR;
4401                 if (r_refdef.fogenabled)
4402                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4403                 if (rsurface.texture->colormapping)
4404                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4405                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4406                         permutation |= SHADERPERMUTATION_REFLECTION;
4407                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4408                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4409         }
4410         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
4411         {
4412                 // ambient model lighting
4413                 mode = SHADERMODE_LIGHTDIRECTION;
4414                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4415                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4416                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4417                         permutation |= SHADERPERMUTATION_GLOW;
4418                 if (r_refdef.fogenabled)
4419                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4420                 if (rsurface.texture->colormapping)
4421                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4422                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4423                         permutation |= SHADERPERMUTATION_REFLECTION;
4424                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4425                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4426         }
4427         else
4428         {
4429                 // lightmapped wall
4430                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
4431                 {
4432                         // deluxemapping (light direction texture)
4433                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
4434                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
4435                         else
4436                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4437                         permutation |= SHADERPERMUTATION_DIFFUSE;
4438                         if (specularscale > 0)
4439                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4440                 }
4441                 else if (r_glsl_deluxemapping.integer >= 2)
4442                 {
4443                         // fake deluxemapping (uniform light direction in tangentspace)
4444                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4445                         permutation |= SHADERPERMUTATION_DIFFUSE;
4446                         if (specularscale > 0)
4447                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4448                 }
4449                 else if (rsurface.uselightmaptexture)
4450                 {
4451                         // ordinary lightmapping (q1bsp, q3bsp)
4452                         mode = SHADERMODE_LIGHTMAP;
4453                 }
4454                 else
4455                 {
4456                         // ordinary vertex coloring (q3bsp)
4457                         mode = SHADERMODE_VERTEXCOLOR;
4458                 }
4459                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4460                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4461                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4462                         permutation |= SHADERPERMUTATION_GLOW;
4463                 if (r_refdef.fogenabled)
4464                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4465                 if (rsurface.texture->colormapping)
4466                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4467                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4468                         permutation |= SHADERPERMUTATION_REFLECTION;
4469                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4470                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4471         }
4472         if(permutation & SHADERPERMUTATION_SPECULAR)
4473                 if(r_shadow_glossexact.integer)
4474                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4475         if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) && r_shadow_usingdeferredprepass)
4476                 permutation |= SHADERPERMUTATION_ALPHAKILL;
4477         switch(vid.renderpath)
4478         {
4479         case RENDERPATH_GL20:
4480                 R_SetupShader_SetPermutationGLSL(mode, permutation);
4481                 if (mode == SHADERMODE_LIGHTSOURCE)
4482                 {
4483                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
4484                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
4485                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
4486                         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);
4487                         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);
4488                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, specularscale, specularscale, specularscale);
4489         
4490                         // additive passes are only darkened by fog, not tinted
4491                         if (r_glsl_permutation->loc_FogColor >= 0)
4492                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4493                         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]);
4494                         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]);
4495                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4496                 }
4497                 else
4498                 {
4499                         if (mode == SHADERMODE_FLATCOLOR)
4500                         {
4501                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
4502                         }
4503                         else if (mode == SHADERMODE_LIGHTDIRECTION)
4504                         {
4505                                 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]);
4506                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity, r_refdef.lightmapintensity, r_refdef.lightmapintensity);
4507                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale);
4508                                 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);
4509                                 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);
4510                                 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]);
4511                                 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]);
4512                         }
4513                         else
4514                         {
4515                                 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]);
4516                                 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]);
4517                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale);
4518                                 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);
4519                                 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);
4520                         }
4521                         // additive passes are only darkened by fog, not tinted
4522                         if (r_glsl_permutation->loc_FogColor >= 0)
4523                         {
4524                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4525                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4526                                 else
4527                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4528                         }
4529                         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);
4530                         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]);
4531                         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]);
4532                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
4533                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
4534                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
4535                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
4536                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4537                 }
4538                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
4539                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
4540                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
4541                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
4542                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
4543                 if (r_glsl_permutation->loc_Color_Pants >= 0)
4544                 {
4545                         if (rsurface.texture->pantstexture)
4546                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4547                         else
4548                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
4549                 }
4550                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
4551                 {
4552                         if (rsurface.texture->shirttexture)
4553                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4554                         else
4555                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
4556                 }
4557                 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]);
4558                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
4559                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
4560                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
4561                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
4562                 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]);
4563
4564         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
4565         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
4566         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
4567                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
4568                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
4569                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
4570                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
4571                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
4572                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
4573                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
4574                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
4575                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
4576                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
4577                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
4578                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_white                                     );
4579                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_blanknormalmap                            );
4580                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
4581                 if (r_glsl_permutation->loc_Texture_Refraction      >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , r_texture_white                                     );
4582                 if (r_glsl_permutation->loc_Texture_Reflection      >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , r_texture_white                                     );
4583                 if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
4584                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
4585                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
4586                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
4587                 if (rsurface.rtlight)
4588                 {
4589                         if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
4590                         if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT     , r_shadow_shadowmaprectangletexture                  );
4591                         if (r_shadow_usingshadowmapcube)
4592                                 if (r_glsl_permutation->loc_Texture_ShadowMapCube   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE     , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
4593                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D       , r_shadow_shadowmap2dtexture                         );
4594                         if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
4595                 }
4596                 CHECKGLERROR
4597                 break;
4598         case RENDERPATH_CGGL:
4599 #ifdef SUPPORTCG
4600                 R_SetupShader_SetPermutationCG(mode, permutation);
4601                 if (mode == SHADERMODE_LIGHTSOURCE)
4602                 {
4603                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
4604                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4605                 }
4606                 else
4607                 {
4608                         if (mode == SHADERMODE_LIGHTDIRECTION)
4609                         {
4610                                 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
4611                         }
4612                 }
4613                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
4614                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
4615                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4616                 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
4617                 CHECKGLERROR
4618
4619                 if (mode == SHADERMODE_LIGHTSOURCE)
4620                 {
4621                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4622                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
4623                         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
4624                         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
4625                         if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, specularscale, specularscale, specularscale);CHECKCGERROR
4626
4627                         // additive passes are only darkened by fog, not tinted
4628                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
4629                         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
4630                         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
4631                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4632                 }
4633                 else
4634                 {
4635                         if (mode == SHADERMODE_FLATCOLOR)
4636                         {
4637                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);CHECKCGERROR
4638                         }
4639                         else if (mode == SHADERMODE_LIGHTDIRECTION)
4640                         {
4641                                 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
4642                                 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, r_refdef.lightmapintensity, r_refdef.lightmapintensity, r_refdef.lightmapintensity);CHECKCGERROR
4643                                 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale);CHECKCGERROR
4644                                 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
4645                                 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
4646                                 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
4647                                 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
4648                         }
4649                         else
4650                         {
4651                                 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
4652                                 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
4653                                 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale);CHECKCGERROR
4654                                 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
4655                                 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
4656                         }
4657                         // additive passes are only darkened by fog, not tinted
4658                         if (r_cg_permutation->fp_FogColor)
4659                         {
4660                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4661                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
4662                                 else
4663                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4664                                 CHECKCGERROR
4665                         }
4666                         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
4667                         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
4668                         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
4669                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
4670                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
4671                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
4672                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
4673                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4674                 }
4675                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
4676                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
4677                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4678                 if (r_cg_permutation->fp_Color_Pants)
4679                 {
4680                         if (rsurface.texture->pantstexture)
4681                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4682                         else
4683                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
4684                         CHECKCGERROR
4685                 }
4686                 if (r_cg_permutation->fp_Color_Shirt)
4687                 {
4688                         if (rsurface.texture->shirttexture)
4689                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4690                         else
4691                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
4692                         CHECKCGERROR
4693                 }
4694                 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
4695                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
4696                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
4697                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
4698                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
4699                 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
4700
4701         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
4702         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
4703         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
4704                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
4705                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
4706                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
4707                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
4708                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
4709                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
4710                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
4711                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
4712                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
4713                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
4714                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
4715                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , r_texture_white                                     );CHECKCGERROR
4716                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , r_texture_blanknormalmap                            );CHECKCGERROR
4717                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
4718                 if (r_cg_permutation->fp_Texture_Refraction     ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction     , r_texture_white                                     );CHECKCGERROR
4719                 if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , r_texture_white                                     );CHECKCGERROR
4720                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
4721                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
4722                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
4723                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
4724                 if (rsurface.rtlight)
4725                 {
4726                         if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
4727                         if (r_cg_permutation->fp_Texture_ShadowMapRect  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
4728                         if (r_shadow_usingshadowmapcube)
4729                                 if (r_cg_permutation->fp_Texture_ShadowMapCube  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
4730                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
4731                         if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
4732                 }
4733
4734                 CHECKGLERROR
4735 #endif
4736                 break;
4737         case RENDERPATH_GL13:
4738         case RENDERPATH_GL11:
4739                 break;
4740         }
4741 }
4742
4743 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
4744 {
4745         // select a permutation of the lighting shader appropriate to this
4746         // combination of texture, entity, light source, and fogging, only use the
4747         // minimum features necessary to avoid wasting rendering time in the
4748         // fragment shader on features that are not being used
4749         unsigned int permutation = 0;
4750         unsigned int mode = 0;
4751         const float *lightcolorbase = rtlight->currentcolor;
4752         float ambientscale = rtlight->ambientscale;
4753         float diffusescale = rtlight->diffusescale;
4754         float specularscale = rtlight->specularscale;
4755         // this is the location of the light in view space
4756         vec3_t viewlightorigin;
4757         // this transforms from view space (camera) to light space (cubemap)
4758         matrix4x4_t viewtolight;
4759         matrix4x4_t lighttoview;
4760         float viewtolight16f[16];
4761         float range = 1.0f / r_shadow_deferred_8bitrange.value;
4762         // light source
4763         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
4764         if (rtlight->currentcubemap != r_texture_whitecube)
4765                 permutation |= SHADERPERMUTATION_CUBEFILTER;
4766         if (diffusescale > 0)
4767                 permutation |= SHADERPERMUTATION_DIFFUSE;
4768         if (specularscale > 0)
4769         {
4770                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4771                 if (r_shadow_glossexact.integer)
4772                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4773         }
4774         if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4775         {
4776                 if (r_shadow_usingshadowmaprect)
4777                         permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4778                 if (r_shadow_usingshadowmap2d)
4779                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4780                 if (r_shadow_usingshadowmapcube)
4781                         permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4782                 else if(r_shadow_shadowmapvsdct)
4783                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4784
4785                 if (r_shadow_shadowmapsampler)
4786                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4787                 if (r_shadow_shadowmappcf > 1)
4788                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4789                 else if (r_shadow_shadowmappcf)
4790                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4791         }
4792         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
4793         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
4794         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
4795         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
4796         switch(vid.renderpath)
4797         {
4798         case RENDERPATH_GL20:
4799                 R_SetupShader_SetPermutationGLSL(mode, permutation);
4800                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
4801                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
4802                 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);
4803                 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);
4804                 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);
4805                 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]);
4806                 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]);
4807                 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));
4808                 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]);
4809
4810                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
4811                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
4812                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
4813                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
4814                 if (r_glsl_permutation->loc_Texture_ShadowMapRect     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT      , r_shadow_shadowmaprectangletexture                  );
4815                 if (r_shadow_usingshadowmapcube)
4816                         if (r_glsl_permutation->loc_Texture_ShadowMapCube     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE      , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
4817                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
4818                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
4819                 break;
4820         case RENDERPATH_CGGL:
4821 #ifdef SUPPORTCG
4822                 R_SetupShader_SetPermutationCG(mode, permutation);
4823                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
4824                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
4825                 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
4826                 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
4827                 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
4828                 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
4829                 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
4830                 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
4831                 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
4832
4833                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
4834                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
4835                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
4836                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
4837                 if (r_cg_permutation->fp_Texture_ShadowMapRect    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
4838                 if (r_shadow_usingshadowmapcube)
4839                         if (r_cg_permutation->fp_Texture_ShadowMapCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
4840                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
4841                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
4842 #endif
4843                 break;
4844         case RENDERPATH_GL13:
4845         case RENDERPATH_GL11:
4846                 break;
4847         }
4848 }
4849
4850 #define SKINFRAME_HASH 1024
4851
4852 typedef struct
4853 {
4854         int loadsequence; // incremented each level change
4855         memexpandablearray_t array;
4856         skinframe_t *hash[SKINFRAME_HASH];
4857 }
4858 r_skinframe_t;
4859 r_skinframe_t r_skinframe;
4860
4861 void R_SkinFrame_PrepareForPurge(void)
4862 {
4863         r_skinframe.loadsequence++;
4864         // wrap it without hitting zero
4865         if (r_skinframe.loadsequence >= 200)
4866                 r_skinframe.loadsequence = 1;
4867 }
4868
4869 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
4870 {
4871         if (!skinframe)
4872                 return;
4873         // mark the skinframe as used for the purging code
4874         skinframe->loadsequence = r_skinframe.loadsequence;
4875 }
4876
4877 void R_SkinFrame_Purge(void)
4878 {
4879         int i;
4880         skinframe_t *s;
4881         for (i = 0;i < SKINFRAME_HASH;i++)
4882         {
4883                 for (s = r_skinframe.hash[i];s;s = s->next)
4884                 {
4885                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
4886                         {
4887                                 if (s->merged == s->base)
4888                                         s->merged = NULL;
4889                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
4890                                 R_PurgeTexture(s->stain );s->stain  = NULL;
4891                                 R_PurgeTexture(s->merged);s->merged = NULL;
4892                                 R_PurgeTexture(s->base  );s->base   = NULL;
4893                                 R_PurgeTexture(s->pants );s->pants  = NULL;
4894                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
4895                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
4896                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
4897                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
4898                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
4899                                 s->loadsequence = 0;
4900                         }
4901                 }
4902         }
4903 }
4904
4905 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
4906         skinframe_t *item;
4907         char basename[MAX_QPATH];
4908
4909         Image_StripImageExtension(name, basename, sizeof(basename));
4910
4911         if( last == NULL ) {
4912                 int hashindex;
4913                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
4914                 item = r_skinframe.hash[hashindex];
4915         } else {
4916                 item = last->next;
4917         }
4918
4919         // linearly search through the hash bucket
4920         for( ; item ; item = item->next ) {
4921                 if( !strcmp( item->basename, basename ) ) {
4922                         return item;
4923                 }
4924         }
4925         return NULL;
4926 }
4927
4928 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
4929 {
4930         skinframe_t *item;
4931         int hashindex;
4932         char basename[MAX_QPATH];
4933
4934         Image_StripImageExtension(name, basename, sizeof(basename));
4935
4936         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
4937         for (item = r_skinframe.hash[hashindex];item;item = item->next)
4938                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
4939                         break;
4940
4941         if (!item) {
4942                 rtexture_t *dyntexture;
4943                 // check whether its a dynamic texture
4944                 dyntexture = CL_GetDynTexture( basename );
4945                 if (!add && !dyntexture)
4946                         return NULL;
4947                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
4948                 memset(item, 0, sizeof(*item));
4949                 strlcpy(item->basename, basename, sizeof(item->basename));
4950                 item->base = dyntexture; // either NULL or dyntexture handle
4951                 item->textureflags = textureflags;
4952                 item->comparewidth = comparewidth;
4953                 item->compareheight = compareheight;
4954                 item->comparecrc = comparecrc;
4955                 item->next = r_skinframe.hash[hashindex];
4956                 r_skinframe.hash[hashindex] = item;
4957         }
4958         else if( item->base == NULL )
4959         {
4960                 rtexture_t *dyntexture;
4961                 // check whether its a dynamic texture
4962                 // 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]
4963                 dyntexture = CL_GetDynTexture( basename );
4964                 item->base = dyntexture; // either NULL or dyntexture handle
4965         }
4966
4967         R_SkinFrame_MarkUsed(item);
4968         return item;
4969 }
4970
4971 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
4972         { \
4973                 unsigned long long avgcolor[5], wsum; \
4974                 int pix, comp, w; \
4975                 avgcolor[0] = 0; \
4976                 avgcolor[1] = 0; \
4977                 avgcolor[2] = 0; \
4978                 avgcolor[3] = 0; \
4979                 avgcolor[4] = 0; \
4980                 wsum = 0; \
4981                 for(pix = 0; pix < cnt; ++pix) \
4982                 { \
4983                         w = 0; \
4984                         for(comp = 0; comp < 3; ++comp) \
4985                                 w += getpixel; \
4986                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
4987                         { \
4988                                 ++wsum; \
4989                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
4990                                 w = getpixel; \
4991                                 for(comp = 0; comp < 3; ++comp) \
4992                                         avgcolor[comp] += getpixel * w; \
4993                                 avgcolor[3] += w; \
4994                         } \
4995                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
4996                         avgcolor[4] += getpixel; \
4997                 } \
4998                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
4999                         avgcolor[3] = 1; \
5000                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5001                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5002                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5003                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5004         }
5005
5006 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5007 {
5008         int j;
5009         unsigned char *pixels;
5010         unsigned char *bumppixels;
5011         unsigned char *basepixels = NULL;
5012         int basepixels_width = 0;
5013         int basepixels_height = 0;
5014         skinframe_t *skinframe;
5015         rtexture_t *ddsbase = NULL;
5016         qboolean ddshasalpha = false;
5017         float ddsavgcolor[4];
5018         char basename[MAX_QPATH];
5019
5020         if (cls.state == ca_dedicated)
5021                 return NULL;
5022
5023         // return an existing skinframe if already loaded
5024         // if loading of the first image fails, don't make a new skinframe as it
5025         // would cause all future lookups of this to be missing
5026         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5027         if (skinframe && skinframe->base)
5028                 return skinframe;
5029
5030         Image_StripImageExtension(name, basename, sizeof(basename));
5031
5032         // check for DDS texture file first
5033         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor)))
5034         {
5035                 basepixels = loadimagepixelsbgra(name, complain, true);
5036                 if (basepixels == NULL)
5037                         return NULL;
5038         }
5039
5040         if (developer_loading.integer)
5041                 Con_Printf("loading skin \"%s\"\n", name);
5042
5043         // we've got some pixels to store, so really allocate this new texture now
5044         if (!skinframe)
5045                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5046         skinframe->stain = NULL;
5047         skinframe->merged = NULL;
5048         skinframe->base = NULL;
5049         skinframe->pants = NULL;
5050         skinframe->shirt = NULL;
5051         skinframe->nmap = NULL;
5052         skinframe->gloss = NULL;
5053         skinframe->glow = NULL;
5054         skinframe->fog = NULL;
5055         skinframe->hasalpha = false;
5056
5057         if (ddsbase)
5058         {
5059                 skinframe->base = ddsbase;
5060                 skinframe->hasalpha = ddshasalpha;
5061                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5062                 if (r_loadfog && skinframe->hasalpha)
5063                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5064                 //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]);
5065         }
5066         else
5067         {
5068                 basepixels_width = image_width;
5069                 basepixels_height = image_height;
5070                 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);
5071                 if (textureflags & TEXF_ALPHA)
5072                 {
5073                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5074                         {
5075                                 if (basepixels[j] < 255)
5076                                 {
5077                                         skinframe->hasalpha = true;
5078                                         break;
5079                                 }
5080                         }
5081                         if (r_loadfog && skinframe->hasalpha)
5082                         {
5083                                 // has transparent pixels
5084                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5085                                 for (j = 0;j < image_width * image_height * 4;j += 4)
5086                                 {
5087                                         pixels[j+0] = 255;
5088                                         pixels[j+1] = 255;
5089                                         pixels[j+2] = 255;
5090                                         pixels[j+3] = basepixels[j+3];
5091                                 }
5092                                 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);
5093                                 Mem_Free(pixels);
5094                         }
5095                 }
5096                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5097                 //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]);
5098                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5099                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true);
5100                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
5101                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true);
5102         }
5103
5104         if (r_loaddds)
5105         {
5106                 if (r_loadnormalmap)
5107                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5108                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL);
5109                 if (r_loadgloss)
5110                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL);
5111                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL);
5112                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL);
5113         }
5114
5115         // _norm is the name used by tenebrae and has been adopted as standard
5116         if (r_loadnormalmap && skinframe->nmap == NULL)
5117         {
5118                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
5119                 {
5120                         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);
5121                         Mem_Free(pixels);
5122                         pixels = NULL;
5123                 }
5124                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
5125                 {
5126                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5127                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5128                         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);
5129                         Mem_Free(pixels);
5130                         Mem_Free(bumppixels);
5131                 }
5132                 else if (r_shadow_bumpscale_basetexture.value > 0)
5133                 {
5134                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5135                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5136                         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);
5137                         Mem_Free(pixels);
5138                 }
5139                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
5140                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true);
5141         }
5142
5143         // _luma is supported only for tenebrae compatibility
5144         // _glow is the preferred name
5145         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false))))
5146         {
5147                 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);
5148                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
5149                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true);
5150                 Mem_Free(pixels);pixels = NULL;
5151         }
5152
5153         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false)))
5154         {
5155                 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);
5156                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
5157                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true);
5158                 Mem_Free(pixels);
5159                 pixels = NULL;
5160         }
5161
5162         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false)))
5163         {
5164                 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);
5165                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
5166                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true);
5167                 Mem_Free(pixels);
5168                 pixels = NULL;
5169         }
5170
5171         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false)))
5172         {
5173                 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);
5174                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
5175                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true);
5176                 Mem_Free(pixels);
5177                 pixels = NULL;
5178         }
5179
5180         if (basepixels)
5181                 Mem_Free(basepixels);
5182
5183         return skinframe;
5184 }
5185
5186 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
5187 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
5188 {
5189         int i;
5190         unsigned char *temp1, *temp2;
5191         skinframe_t *skinframe;
5192
5193         if (cls.state == ca_dedicated)
5194                 return NULL;
5195
5196         // if already loaded just return it, otherwise make a new skinframe
5197         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
5198         if (skinframe && skinframe->base)
5199                 return skinframe;
5200
5201         skinframe->stain = NULL;
5202         skinframe->merged = NULL;
5203         skinframe->base = NULL;
5204         skinframe->pants = NULL;
5205         skinframe->shirt = NULL;
5206         skinframe->nmap = NULL;
5207         skinframe->gloss = NULL;
5208         skinframe->glow = NULL;
5209         skinframe->fog = NULL;
5210         skinframe->hasalpha = false;
5211
5212         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5213         if (!skindata)
5214                 return NULL;
5215
5216         if (developer_loading.integer)
5217                 Con_Printf("loading 32bit skin \"%s\"\n", name);
5218
5219         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
5220         {
5221                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5222                 temp2 = temp1 + width * height * 4;
5223                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5224                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5225                 Mem_Free(temp1);
5226         }
5227         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5228         if (textureflags & TEXF_ALPHA)
5229         {
5230                 for (i = 3;i < width * height * 4;i += 4)
5231                 {
5232                         if (skindata[i] < 255)
5233                         {
5234                                 skinframe->hasalpha = true;
5235                                 break;
5236                         }
5237                 }
5238                 if (r_loadfog && skinframe->hasalpha)
5239                 {
5240                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
5241                         memcpy(fogpixels, skindata, width * height * 4);
5242                         for (i = 0;i < width * height * 4;i += 4)
5243                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
5244                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5245                         Mem_Free(fogpixels);
5246                 }
5247         }
5248
5249         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
5250         //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]);
5251
5252         return skinframe;
5253 }
5254
5255 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
5256 {
5257         int i;
5258         int featuresmask;
5259         skinframe_t *skinframe;
5260
5261         if (cls.state == ca_dedicated)
5262                 return NULL;
5263
5264         // if already loaded just return it, otherwise make a new skinframe
5265         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5266         if (skinframe && skinframe->base)
5267                 return skinframe;
5268
5269         skinframe->stain = NULL;
5270         skinframe->merged = NULL;
5271         skinframe->base = NULL;
5272         skinframe->pants = NULL;
5273         skinframe->shirt = NULL;
5274         skinframe->nmap = NULL;
5275         skinframe->gloss = NULL;
5276         skinframe->glow = NULL;
5277         skinframe->fog = NULL;
5278         skinframe->hasalpha = false;
5279
5280         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5281         if (!skindata)
5282                 return NULL;
5283
5284         if (developer_loading.integer)
5285                 Con_Printf("loading quake skin \"%s\"\n", name);
5286
5287         // 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)
5288         skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
5289         memcpy(skinframe->qpixels, skindata, width*height);
5290         skinframe->qwidth = width;
5291         skinframe->qheight = height;
5292
5293         featuresmask = 0;
5294         for (i = 0;i < width * height;i++)
5295                 featuresmask |= palette_featureflags[skindata[i]];
5296
5297         skinframe->hasalpha = false;
5298         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
5299         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
5300         skinframe->qgeneratemerged = true;
5301         skinframe->qgeneratebase = skinframe->qhascolormapping;
5302         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
5303
5304         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
5305         //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]);
5306
5307         return skinframe;
5308 }
5309
5310 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
5311 {
5312         int width;
5313         int height;
5314         unsigned char *skindata;
5315
5316         if (!skinframe->qpixels)
5317                 return;
5318
5319         if (!skinframe->qhascolormapping)
5320                 colormapped = false;
5321
5322         if (colormapped)
5323         {
5324                 if (!skinframe->qgeneratebase)
5325                         return;
5326         }
5327         else
5328         {
5329                 if (!skinframe->qgeneratemerged)
5330                         return;
5331         }
5332
5333         width = skinframe->qwidth;
5334         height = skinframe->qheight;
5335         skindata = skinframe->qpixels;
5336
5337         if (skinframe->qgeneratenmap)
5338         {
5339                 unsigned char *temp1, *temp2;
5340                 skinframe->qgeneratenmap = false;
5341                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5342                 temp2 = temp1 + width * height * 4;
5343                 // use either a custom palette or the quake palette
5344                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
5345                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5346                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5347                 Mem_Free(temp1);
5348         }
5349
5350         if (skinframe->qgenerateglow)
5351         {
5352                 skinframe->qgenerateglow = false;
5353                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
5354         }
5355
5356         if (colormapped)
5357         {
5358                 skinframe->qgeneratebase = false;
5359                 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);
5360                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
5361                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
5362         }
5363         else
5364         {
5365                 skinframe->qgeneratemerged = false;
5366                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
5367         }
5368
5369         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
5370         {
5371                 Mem_Free(skinframe->qpixels);
5372                 skinframe->qpixels = NULL;
5373         }
5374 }
5375
5376 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)
5377 {
5378         int i;
5379         skinframe_t *skinframe;
5380
5381         if (cls.state == ca_dedicated)
5382                 return NULL;
5383
5384         // if already loaded just return it, otherwise make a new skinframe
5385         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5386         if (skinframe && skinframe->base)
5387                 return skinframe;
5388
5389         skinframe->stain = NULL;
5390         skinframe->merged = NULL;
5391         skinframe->base = NULL;
5392         skinframe->pants = NULL;
5393         skinframe->shirt = NULL;
5394         skinframe->nmap = NULL;
5395         skinframe->gloss = NULL;
5396         skinframe->glow = NULL;
5397         skinframe->fog = NULL;
5398         skinframe->hasalpha = false;
5399
5400         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5401         if (!skindata)
5402                 return NULL;
5403
5404         if (developer_loading.integer)
5405                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
5406
5407         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
5408         if (textureflags & TEXF_ALPHA)
5409         {
5410                 for (i = 0;i < width * height;i++)
5411                 {
5412                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
5413                         {
5414                                 skinframe->hasalpha = true;
5415                                 break;
5416                         }
5417                 }
5418                 if (r_loadfog && skinframe->hasalpha)
5419                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
5420         }
5421
5422         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
5423         //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]);
5424
5425         return skinframe;
5426 }
5427
5428 skinframe_t *R_SkinFrame_LoadMissing(void)
5429 {
5430         skinframe_t *skinframe;
5431
5432         if (cls.state == ca_dedicated)
5433                 return NULL;
5434
5435         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
5436         skinframe->stain = NULL;
5437         skinframe->merged = NULL;
5438         skinframe->base = NULL;
5439         skinframe->pants = NULL;
5440         skinframe->shirt = NULL;
5441         skinframe->nmap = NULL;
5442         skinframe->gloss = NULL;
5443         skinframe->glow = NULL;
5444         skinframe->fog = NULL;
5445         skinframe->hasalpha = false;
5446
5447         skinframe->avgcolor[0] = rand() / RAND_MAX;
5448         skinframe->avgcolor[1] = rand() / RAND_MAX;
5449         skinframe->avgcolor[2] = rand() / RAND_MAX;
5450         skinframe->avgcolor[3] = 1;
5451
5452         return skinframe;
5453 }
5454
5455 void R_Main_FreeViewCache(void)
5456 {
5457         if (r_refdef.viewcache.entityvisible)
5458                 Mem_Free(r_refdef.viewcache.entityvisible);
5459         if (r_refdef.viewcache.world_pvsbits)
5460                 Mem_Free(r_refdef.viewcache.world_pvsbits);
5461         if (r_refdef.viewcache.world_leafvisible)
5462                 Mem_Free(r_refdef.viewcache.world_leafvisible);
5463         if (r_refdef.viewcache.world_surfacevisible)
5464                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
5465         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
5466 }
5467
5468 void R_Main_ResizeViewCache(void)
5469 {
5470         int numentities = r_refdef.scene.numentities;
5471         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
5472         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
5473         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
5474         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
5475         if (r_refdef.viewcache.maxentities < numentities)
5476         {
5477                 r_refdef.viewcache.maxentities = numentities;
5478                 if (r_refdef.viewcache.entityvisible)
5479                         Mem_Free(r_refdef.viewcache.entityvisible);
5480                 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
5481         }
5482         if (r_refdef.viewcache.world_numclusters != numclusters)
5483         {
5484                 r_refdef.viewcache.world_numclusters = numclusters;
5485                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
5486                 if (r_refdef.viewcache.world_pvsbits)
5487                         Mem_Free(r_refdef.viewcache.world_pvsbits);
5488                 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
5489         }
5490         if (r_refdef.viewcache.world_numleafs != numleafs)
5491         {
5492                 r_refdef.viewcache.world_numleafs = numleafs;
5493                 if (r_refdef.viewcache.world_leafvisible)
5494                         Mem_Free(r_refdef.viewcache.world_leafvisible);
5495                 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
5496         }
5497         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
5498         {
5499                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
5500                 if (r_refdef.viewcache.world_surfacevisible)
5501                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
5502                 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
5503         }
5504 }
5505
5506 extern rtexture_t *loadingscreentexture;
5507 void gl_main_start(void)
5508 {
5509         loadingscreentexture = NULL;
5510         r_texture_blanknormalmap = NULL;
5511         r_texture_white = NULL;
5512         r_texture_grey128 = NULL;
5513         r_texture_black = NULL;
5514         r_texture_whitecube = NULL;
5515         r_texture_normalizationcube = NULL;
5516         r_texture_fogattenuation = NULL;
5517         r_texture_gammaramps = NULL;
5518
5519         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
5520         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
5521
5522         switch(vid.renderpath)
5523         {
5524         case RENDERPATH_GL20:
5525         case RENDERPATH_CGGL:
5526                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5527                 Cvar_SetValueQuick(&gl_combine, 1);
5528                 Cvar_SetValueQuick(&r_glsl, 1);
5529                 r_loadnormalmap = true;
5530                 r_loadgloss = true;
5531                 r_loadfog = false;
5532                 break;
5533         case RENDERPATH_GL13:
5534                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5535                 Cvar_SetValueQuick(&gl_combine, 1);
5536                 Cvar_SetValueQuick(&r_glsl, 0);
5537                 r_loadnormalmap = false;
5538                 r_loadgloss = false;
5539                 r_loadfog = true;
5540                 break;
5541         case RENDERPATH_GL11:
5542                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5543                 Cvar_SetValueQuick(&gl_combine, 0);
5544                 Cvar_SetValueQuick(&r_glsl, 0);
5545                 r_loadnormalmap = false;
5546                 r_loadgloss = false;
5547                 r_loadfog = true;
5548                 break;
5549         }
5550
5551         R_AnimCache_Free();
5552         R_FrameData_Reset();
5553
5554         r_numqueries = 0;
5555         r_maxqueries = 0;
5556         memset(r_queries, 0, sizeof(r_queries));
5557
5558         r_qwskincache = NULL;
5559         r_qwskincache_size = 0;
5560
5561         // set up r_skinframe loading system for textures
5562         memset(&r_skinframe, 0, sizeof(r_skinframe));
5563         r_skinframe.loadsequence = 1;
5564         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
5565
5566         r_main_texturepool = R_AllocTexturePool();
5567         R_BuildBlankTextures();
5568         R_BuildNoTexture();
5569         if (vid.support.arb_texture_cube_map)
5570         {
5571                 R_BuildWhiteCube();
5572                 R_BuildNormalizationCube();
5573         }
5574         r_texture_fogattenuation = NULL;
5575         r_texture_gammaramps = NULL;
5576         //r_texture_fogintensity = NULL;
5577         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
5578         memset(&r_waterstate, 0, sizeof(r_waterstate));
5579         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5580         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
5581 #ifdef SUPPORTCG
5582         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5583         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
5584 #endif
5585         memset(&r_svbsp, 0, sizeof (r_svbsp));
5586
5587         r_refdef.fogmasktable_density = 0;
5588 }
5589
5590 void gl_main_shutdown(void)
5591 {
5592         R_AnimCache_Free();
5593         R_FrameData_Reset();
5594
5595         R_Main_FreeViewCache();
5596
5597         if (r_maxqueries)
5598                 qglDeleteQueriesARB(r_maxqueries, r_queries);
5599
5600         r_numqueries = 0;
5601         r_maxqueries = 0;
5602         memset(r_queries, 0, sizeof(r_queries));
5603
5604         r_qwskincache = NULL;
5605         r_qwskincache_size = 0;
5606
5607         // clear out the r_skinframe state
5608         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
5609         memset(&r_skinframe, 0, sizeof(r_skinframe));
5610
5611         if (r_svbsp.nodes)
5612                 Mem_Free(r_svbsp.nodes);
5613         memset(&r_svbsp, 0, sizeof (r_svbsp));
5614         R_FreeTexturePool(&r_main_texturepool);
5615         loadingscreentexture = NULL;
5616         r_texture_blanknormalmap = NULL;
5617         r_texture_white = NULL;
5618         r_texture_grey128 = NULL;
5619         r_texture_black = NULL;
5620         r_texture_whitecube = NULL;
5621         r_texture_normalizationcube = NULL;
5622         r_texture_fogattenuation = NULL;
5623         r_texture_gammaramps = NULL;
5624         //r_texture_fogintensity = NULL;
5625         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
5626         memset(&r_waterstate, 0, sizeof(r_waterstate));
5627         R_GLSL_Restart_f();
5628 }
5629
5630 extern void CL_ParseEntityLump(char *entitystring);
5631 void gl_main_newmap(void)
5632 {
5633         // FIXME: move this code to client
5634         int l;
5635         char *entities, entname[MAX_QPATH];
5636         if (r_qwskincache)
5637                 Mem_Free(r_qwskincache);
5638         r_qwskincache = NULL;
5639         r_qwskincache_size = 0;
5640         if (cl.worldmodel)
5641         {
5642                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
5643                 l = (int)strlen(entname) - 4;
5644                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
5645                 {
5646                         memcpy(entname + l, ".ent", 5);
5647                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
5648                         {
5649                                 CL_ParseEntityLump(entities);
5650                                 Mem_Free(entities);
5651                                 return;
5652                         }
5653                 }
5654                 if (cl.worldmodel->brush.entities)
5655                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
5656         }
5657         R_Main_FreeViewCache();
5658
5659         R_FrameData_Reset();
5660 }
5661
5662 void GL_Main_Init(void)
5663 {
5664         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
5665
5666         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
5667         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
5668         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
5669         if (gamemode == GAME_NEHAHRA)
5670         {
5671                 Cvar_RegisterVariable (&gl_fogenable);
5672                 Cvar_RegisterVariable (&gl_fogdensity);
5673                 Cvar_RegisterVariable (&gl_fogred);
5674                 Cvar_RegisterVariable (&gl_foggreen);
5675                 Cvar_RegisterVariable (&gl_fogblue);
5676                 Cvar_RegisterVariable (&gl_fogstart);
5677                 Cvar_RegisterVariable (&gl_fogend);
5678                 Cvar_RegisterVariable (&gl_skyclip);
5679         }
5680         Cvar_RegisterVariable(&r_motionblur);
5681         Cvar_RegisterVariable(&r_motionblur_maxblur);
5682         Cvar_RegisterVariable(&r_motionblur_bmin);
5683         Cvar_RegisterVariable(&r_motionblur_vmin);
5684         Cvar_RegisterVariable(&r_motionblur_vmax);
5685         Cvar_RegisterVariable(&r_motionblur_vcoeff);
5686         Cvar_RegisterVariable(&r_motionblur_randomize);
5687         Cvar_RegisterVariable(&r_damageblur);
5688         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
5689         Cvar_RegisterVariable(&r_equalize_entities_minambient);
5690         Cvar_RegisterVariable(&r_equalize_entities_by);
5691         Cvar_RegisterVariable(&r_equalize_entities_to);
5692         Cvar_RegisterVariable(&r_depthfirst);
5693         Cvar_RegisterVariable(&r_useinfinitefarclip);
5694         Cvar_RegisterVariable(&r_farclip_base);
5695         Cvar_RegisterVariable(&r_farclip_world);
5696         Cvar_RegisterVariable(&r_nearclip);
5697         Cvar_RegisterVariable(&r_showbboxes);
5698         Cvar_RegisterVariable(&r_showsurfaces);
5699         Cvar_RegisterVariable(&r_showtris);
5700         Cvar_RegisterVariable(&r_shownormals);
5701         Cvar_RegisterVariable(&r_showlighting);
5702         Cvar_RegisterVariable(&r_showshadowvolumes);
5703         Cvar_RegisterVariable(&r_showcollisionbrushes);
5704         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
5705         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
5706         Cvar_RegisterVariable(&r_showdisabledepthtest);
5707         Cvar_RegisterVariable(&r_drawportals);
5708         Cvar_RegisterVariable(&r_drawentities);
5709         Cvar_RegisterVariable(&r_cullentities_trace);
5710         Cvar_RegisterVariable(&r_cullentities_trace_samples);
5711         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
5712         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
5713         Cvar_RegisterVariable(&r_cullentities_trace_delay);
5714         Cvar_RegisterVariable(&r_drawviewmodel);
5715         Cvar_RegisterVariable(&r_speeds);
5716         Cvar_RegisterVariable(&r_fullbrights);
5717         Cvar_RegisterVariable(&r_wateralpha);
5718         Cvar_RegisterVariable(&r_dynamic);
5719         Cvar_RegisterVariable(&r_fullbright);
5720         Cvar_RegisterVariable(&r_shadows);
5721         Cvar_RegisterVariable(&r_shadows_darken);
5722         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
5723         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
5724         Cvar_RegisterVariable(&r_shadows_throwdistance);
5725         Cvar_RegisterVariable(&r_shadows_throwdirection);
5726         Cvar_RegisterVariable(&r_q1bsp_skymasking);
5727         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
5728         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
5729         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
5730         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
5731         Cvar_RegisterVariable(&r_fog_exp2);
5732         Cvar_RegisterVariable(&r_drawfog);
5733         Cvar_RegisterVariable(&r_transparentdepthmasking);
5734         Cvar_RegisterVariable(&r_texture_dds_load);
5735         Cvar_RegisterVariable(&r_texture_dds_save);
5736         Cvar_RegisterVariable(&r_textureunits);
5737         Cvar_RegisterVariable(&gl_combine);
5738         Cvar_RegisterVariable(&r_glsl);
5739         Cvar_RegisterVariable(&r_glsl_deluxemapping);
5740         Cvar_RegisterVariable(&r_glsl_offsetmapping);
5741         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
5742         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
5743         Cvar_RegisterVariable(&r_glsl_postprocess);
5744         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
5745         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
5746         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
5747         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
5748         Cvar_RegisterVariable(&r_water);
5749         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
5750         Cvar_RegisterVariable(&r_water_clippingplanebias);
5751         Cvar_RegisterVariable(&r_water_refractdistort);
5752         Cvar_RegisterVariable(&r_water_reflectdistort);
5753         Cvar_RegisterVariable(&r_lerpsprites);
5754         Cvar_RegisterVariable(&r_lerpmodels);
5755         Cvar_RegisterVariable(&r_lerplightstyles);
5756         Cvar_RegisterVariable(&r_waterscroll);
5757         Cvar_RegisterVariable(&r_bloom);
5758         Cvar_RegisterVariable(&r_bloom_colorscale);
5759         Cvar_RegisterVariable(&r_bloom_brighten);
5760         Cvar_RegisterVariable(&r_bloom_blur);
5761         Cvar_RegisterVariable(&r_bloom_resolution);
5762         Cvar_RegisterVariable(&r_bloom_colorexponent);
5763         Cvar_RegisterVariable(&r_bloom_colorsubtract);
5764         Cvar_RegisterVariable(&r_hdr);
5765         Cvar_RegisterVariable(&r_hdr_scenebrightness);
5766         Cvar_RegisterVariable(&r_hdr_glowintensity);
5767         Cvar_RegisterVariable(&r_hdr_range);
5768         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
5769         Cvar_RegisterVariable(&developer_texturelogging);
5770         Cvar_RegisterVariable(&gl_lightmaps);
5771         Cvar_RegisterVariable(&r_test);
5772         Cvar_RegisterVariable(&r_batchmode);
5773         Cvar_RegisterVariable(&r_glsl_saturation);
5774         Cvar_RegisterVariable(&r_framedatasize);
5775         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
5776                 Cvar_SetValue("r_fullbrights", 0);
5777         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
5778
5779         Cvar_RegisterVariable(&r_track_sprites);
5780         Cvar_RegisterVariable(&r_track_sprites_flags);
5781         Cvar_RegisterVariable(&r_track_sprites_scalew);
5782         Cvar_RegisterVariable(&r_track_sprites_scaleh);
5783 }
5784
5785 extern void R_Textures_Init(void);
5786 extern void GL_Draw_Init(void);
5787 extern void GL_Main_Init(void);
5788 extern void R_Shadow_Init(void);
5789 extern void R_Sky_Init(void);
5790 extern void GL_Surf_Init(void);
5791 extern void R_Particles_Init(void);
5792 extern void R_Explosion_Init(void);
5793 extern void gl_backend_init(void);
5794 extern void Sbar_Init(void);
5795 extern void R_LightningBeams_Init(void);
5796 extern void Mod_RenderInit(void);
5797 extern void Font_Init(void);
5798
5799 void Render_Init(void)
5800 {
5801         gl_backend_init();
5802         R_Textures_Init();
5803         GL_Main_Init();
5804         Font_Init();
5805         GL_Draw_Init();
5806         R_Shadow_Init();
5807         R_Sky_Init();
5808         GL_Surf_Init();
5809         Sbar_Init();
5810         R_Particles_Init();
5811         R_Explosion_Init();
5812         R_LightningBeams_Init();
5813         Mod_RenderInit();
5814 }
5815
5816 /*
5817 ===============
5818 GL_Init
5819 ===============
5820 */
5821 extern char *ENGINE_EXTENSIONS;
5822 void GL_Init (void)
5823 {
5824         gl_renderer = (const char *)qglGetString(GL_RENDERER);
5825         gl_vendor = (const char *)qglGetString(GL_VENDOR);
5826         gl_version = (const char *)qglGetString(GL_VERSION);
5827         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
5828
5829         if (!gl_extensions)
5830                 gl_extensions = "";
5831         if (!gl_platformextensions)
5832                 gl_platformextensions = "";
5833
5834         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
5835         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
5836         Con_Printf("GL_VERSION: %s\n", gl_version);
5837         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
5838         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
5839
5840         VID_CheckExtensions();
5841
5842         // LordHavoc: report supported extensions
5843         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
5844
5845         // clear to black (loading plaque will be seen over this)
5846         CHECKGLERROR
5847         qglClearColor(0,0,0,1);CHECKGLERROR
5848         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
5849 }
5850
5851 int R_CullBox(const vec3_t mins, const vec3_t maxs)
5852 {
5853         int i;
5854         mplane_t *p;
5855         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5856         {
5857                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
5858                 if (i == 4)
5859                         continue;
5860                 p = r_refdef.view.frustum + i;
5861                 switch(p->signbits)
5862                 {
5863                 default:
5864                 case 0:
5865                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5866                                 return true;
5867                         break;
5868                 case 1:
5869                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5870                                 return true;
5871                         break;
5872                 case 2:
5873                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5874                                 return true;
5875                         break;
5876                 case 3:
5877                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5878                                 return true;
5879                         break;
5880                 case 4:
5881                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5882                                 return true;
5883                         break;
5884                 case 5:
5885                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5886                                 return true;
5887                         break;
5888                 case 6:
5889                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5890                                 return true;
5891                         break;
5892                 case 7:
5893                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5894                                 return true;
5895                         break;
5896                 }
5897         }
5898         return false;
5899 }
5900
5901 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
5902 {
5903         int i;
5904         const mplane_t *p;
5905         for (i = 0;i < numplanes;i++)
5906         {
5907                 p = planes + i;
5908                 switch(p->signbits)
5909                 {
5910                 default:
5911                 case 0:
5912                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5913                                 return true;
5914                         break;
5915                 case 1:
5916                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5917                                 return true;
5918                         break;
5919                 case 2:
5920                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5921                                 return true;
5922                         break;
5923                 case 3:
5924                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5925                                 return true;
5926                         break;
5927                 case 4:
5928                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5929                                 return true;
5930                         break;
5931                 case 5:
5932                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5933                                 return true;
5934                         break;
5935                 case 6:
5936                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5937                                 return true;
5938                         break;
5939                 case 7:
5940                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5941                                 return true;
5942                         break;
5943                 }
5944         }
5945         return false;
5946 }
5947
5948 //==================================================================================
5949
5950 // LordHavoc: this stores temporary data used within the same frame
5951
5952 qboolean r_framedata_failed;
5953 static size_t r_framedata_size;
5954 static size_t r_framedata_current;
5955 static void *r_framedata_base;
5956
5957 void R_FrameData_Reset(void)
5958 {
5959         if (r_framedata_base)
5960                 Mem_Free(r_framedata_base);
5961         r_framedata_base = NULL;
5962         r_framedata_size = 0;
5963         r_framedata_current = 0;
5964         r_framedata_failed = false;
5965 }
5966
5967 void R_FrameData_NewFrame(void)
5968 {
5969         size_t wantedsize;
5970         if (r_framedata_failed)
5971                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
5972         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
5973         wantedsize = bound(65536, wantedsize, 128*1024*1024);
5974         if (r_framedata_size != wantedsize)
5975         {
5976                 r_framedata_size = wantedsize;
5977                 if (r_framedata_base)
5978                         Mem_Free(r_framedata_base);
5979                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
5980         }
5981         r_framedata_current = 0;
5982         r_framedata_failed = false;
5983 }
5984
5985 void *R_FrameData_Alloc(size_t size)
5986 {
5987         void *data;
5988
5989         // align to 16 byte boundary
5990         size = (size + 15) & ~15;
5991         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
5992         r_framedata_current += size;
5993
5994         // check overflow
5995         if (r_framedata_current > r_framedata_size)
5996                 r_framedata_failed = true;
5997
5998         // return NULL on everything after a failure
5999         if (r_framedata_failed)
6000                 return NULL;
6001
6002         return data;
6003 }
6004
6005 void *R_FrameData_Store(size_t size, void *data)
6006 {
6007         void *d = R_FrameData_Alloc(size);
6008         if (d)
6009                 memcpy(d, data, size);
6010         return d;
6011 }
6012
6013 //==================================================================================
6014
6015 // LordHavoc: animcache originally written by Echon, rewritten since then
6016
6017 /**
6018  * Animation cache prevents re-generating mesh data for an animated model
6019  * multiple times in one frame for lighting, shadowing, reflections, etc.
6020  */
6021
6022 void R_AnimCache_Free(void)
6023 {
6024 }
6025
6026 void R_AnimCache_ClearCache(void)
6027 {
6028         int i;
6029         entity_render_t *ent;
6030
6031         for (i = 0;i < r_refdef.scene.numentities;i++)
6032         {
6033                 ent = r_refdef.scene.entities[i];
6034                 ent->animcache_vertex3f = NULL;
6035                 ent->animcache_normal3f = NULL;
6036                 ent->animcache_svector3f = NULL;
6037                 ent->animcache_tvector3f = NULL;
6038         }
6039 }
6040
6041 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6042 {
6043         dp_model_t *model = ent->model;
6044         int numvertices;
6045         // see if it's already cached this frame
6046         if (ent->animcache_vertex3f)
6047         {
6048                 // add normals/tangents if needed
6049                 if (wantnormals || wanttangents)
6050                 {
6051                         if (ent->animcache_normal3f)
6052                                 wantnormals = false;
6053                         if (ent->animcache_svector3f)
6054                                 wanttangents = false;
6055                         if (wantnormals || wanttangents)
6056                         {
6057                                 numvertices = model->surfmesh.num_vertices;
6058                                 if (wantnormals)
6059                                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6060                                 if (wanttangents)
6061                                 {
6062                                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6063                                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6064                                 }
6065                                 if (!r_framedata_failed)
6066                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
6067                         }
6068                 }
6069         }
6070         else
6071         {
6072                 // see if this ent is worth caching
6073                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
6074                         return false;
6075                 // get some memory for this entity and generate mesh data
6076                 numvertices = model->surfmesh.num_vertices;
6077                 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6078                 if (wantnormals)
6079                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6080                 if (wanttangents)
6081                 {
6082                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6083                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6084                 }
6085                 if (!r_framedata_failed)
6086                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
6087         }
6088         return !r_framedata_failed;
6089 }
6090
6091 void R_AnimCache_CacheVisibleEntities(void)
6092 {
6093         int i;
6094         qboolean wantnormals = !r_showsurfaces.integer;
6095         qboolean wanttangents = !r_showsurfaces.integer;
6096
6097         switch(vid.renderpath)
6098         {
6099         case RENDERPATH_GL20:
6100         case RENDERPATH_CGGL:
6101                 break;
6102         case RENDERPATH_GL13:
6103         case RENDERPATH_GL11:
6104                 wanttangents = false;
6105                 break;
6106         }
6107
6108         // TODO: thread this
6109         // NOTE: R_PrepareRTLights() also caches entities
6110
6111         for (i = 0;i < r_refdef.scene.numentities;i++)
6112                 if (r_refdef.viewcache.entityvisible[i])
6113                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
6114
6115         if (r_shadows.integer)
6116                 for (i = 0;i < r_refdef.scene.numentities;i++)
6117                         if (!r_refdef.viewcache.entityvisible[i])
6118                                 R_AnimCache_GetEntity(r_refdef.scene.entities[i], false, false);
6119 }
6120
6121 //==================================================================================
6122
6123 static void R_View_UpdateEntityLighting (void)
6124 {
6125         int i;
6126         entity_render_t *ent;
6127         vec3_t tempdiffusenormal, avg;
6128         vec_t f, fa, fd, fdd;
6129
6130         for (i = 0;i < r_refdef.scene.numentities;i++)
6131         {
6132                 ent = r_refdef.scene.entities[i];
6133
6134                 // skip unseen models
6135                 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
6136                         continue;
6137
6138                 // skip bsp models
6139                 if (ent->model && ent->model->brush.num_leafs)
6140                 {
6141                         // TODO: use modellight for r_ambient settings on world?
6142                         VectorSet(ent->modellight_ambient, 0, 0, 0);
6143                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
6144                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
6145                         continue;
6146                 }
6147
6148                 // fetch the lighting from the worldmodel data
6149                 VectorClear(ent->modellight_ambient);
6150                 VectorClear(ent->modellight_diffuse);
6151                 VectorClear(tempdiffusenormal);
6152                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
6153                 {
6154                         vec3_t org;
6155                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6156                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
6157                         if(ent->flags & RENDER_EQUALIZE)
6158                         {
6159                                 // first fix up ambient lighting...
6160                                 if(r_equalize_entities_minambient.value > 0)
6161                                 {
6162                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
6163                                         if(fd > 0)
6164                                         {
6165                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
6166                                                 if(fa < r_equalize_entities_minambient.value * fd)
6167                                                 {
6168                                                         // solve:
6169                                                         //   fa'/fd' = minambient
6170                                                         //   fa'+0.25*fd' = fa+0.25*fd
6171                                                         //   ...
6172                                                         //   fa' = fd' * minambient
6173                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
6174                                                         //   ...
6175                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
6176                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
6177                                                         //   ...
6178                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
6179                                                         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
6180                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
6181                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6182                                                 }
6183                                         }
6184                                 }
6185
6186                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
6187                                 {
6188                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
6189                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
6190                                         if(f > 0)
6191                                         {
6192                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
6193                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
6194                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6195                                         }
6196                                 }
6197                         }
6198                 }
6199                 else // highly rare
6200                         VectorSet(ent->modellight_ambient, 1, 1, 1);
6201
6202                 // move the light direction into modelspace coordinates for lighting code
6203                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
6204                 if(VectorLength2(ent->modellight_lightdir) == 0)
6205                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
6206                 VectorNormalize(ent->modellight_lightdir);
6207         }
6208 }
6209
6210 #define MAX_LINEOFSIGHTTRACES 64
6211
6212 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
6213 {
6214         int i;
6215         vec3_t boxmins, boxmaxs;
6216         vec3_t start;
6217         vec3_t end;
6218         dp_model_t *model = r_refdef.scene.worldmodel;
6219
6220         if (!model || !model->brush.TraceLineOfSight)
6221                 return true;
6222
6223         // expand the box a little
6224         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
6225         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
6226         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
6227         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
6228         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
6229         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
6230
6231         // try center
6232         VectorCopy(eye, start);
6233         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
6234         if (model->brush.TraceLineOfSight(model, start, end))
6235                 return true;
6236
6237         // try various random positions
6238         for (i = 0;i < numsamples;i++)
6239         {
6240                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
6241                 if (model->brush.TraceLineOfSight(model, start, end))
6242                         return true;
6243         }
6244
6245         return false;
6246 }
6247
6248
6249 static void R_View_UpdateEntityVisible (void)
6250 {
6251         int i;
6252         int renderimask;
6253         int samples;
6254         entity_render_t *ent;
6255
6256         renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
6257         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
6258         {
6259                 // worldmodel can check visibility
6260                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
6261                 for (i = 0;i < r_refdef.scene.numentities;i++)
6262                 {
6263                         ent = r_refdef.scene.entities[i];
6264                         if (!(ent->flags & renderimask))
6265                         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)))
6266                         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))
6267                                 r_refdef.viewcache.entityvisible[i] = true;
6268                 }
6269                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
6270                 {
6271                         for (i = 0;i < r_refdef.scene.numentities;i++)
6272                         {
6273                                 ent = r_refdef.scene.entities[i];
6274                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
6275                                 {
6276                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
6277                                         if (samples < 0)
6278                                                 continue; // temp entities do pvs only
6279                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
6280                                                 ent->last_trace_visibility = realtime;
6281                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
6282                                                 r_refdef.viewcache.entityvisible[i] = 0;
6283                                 }
6284                         }
6285                 }
6286         }
6287         else
6288         {
6289                 // no worldmodel or it can't check visibility
6290                 for (i = 0;i < r_refdef.scene.numentities;i++)
6291                 {
6292                         ent = r_refdef.scene.entities[i];
6293                         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));
6294                 }
6295         }
6296 }
6297
6298 /// only used if skyrendermasked, and normally returns false
6299 int R_DrawBrushModelsSky (void)
6300 {
6301         int i, sky;
6302         entity_render_t *ent;
6303
6304         sky = false;
6305         for (i = 0;i < r_refdef.scene.numentities;i++)
6306         {
6307                 if (!r_refdef.viewcache.entityvisible[i])
6308                         continue;
6309                 ent = r_refdef.scene.entities[i];
6310                 if (!ent->model || !ent->model->DrawSky)
6311                         continue;
6312                 ent->model->DrawSky(ent);
6313                 sky = true;
6314         }
6315         return sky;
6316 }
6317
6318 static void R_DrawNoModel(entity_render_t *ent);
6319 static void R_DrawModels(void)
6320 {
6321         int i;
6322         entity_render_t *ent;
6323
6324         for (i = 0;i < r_refdef.scene.numentities;i++)
6325         {
6326                 if (!r_refdef.viewcache.entityvisible[i])
6327                         continue;
6328                 ent = r_refdef.scene.entities[i];
6329                 r_refdef.stats.entities++;
6330                 if (ent->model && ent->model->Draw != NULL)
6331                         ent->model->Draw(ent);
6332                 else
6333                         R_DrawNoModel(ent);
6334         }
6335 }
6336
6337 static void R_DrawModelsDepth(void)
6338 {
6339         int i;
6340         entity_render_t *ent;
6341
6342         for (i = 0;i < r_refdef.scene.numentities;i++)
6343         {
6344                 if (!r_refdef.viewcache.entityvisible[i])
6345                         continue;
6346                 ent = r_refdef.scene.entities[i];
6347                 if (ent->model && ent->model->DrawDepth != NULL)
6348                         ent->model->DrawDepth(ent);
6349         }
6350 }
6351
6352 static void R_DrawModelsDebug(void)
6353 {
6354         int i;
6355         entity_render_t *ent;
6356
6357         for (i = 0;i < r_refdef.scene.numentities;i++)
6358         {
6359                 if (!r_refdef.viewcache.entityvisible[i])
6360                         continue;
6361                 ent = r_refdef.scene.entities[i];
6362                 if (ent->model && ent->model->DrawDebug != NULL)
6363                         ent->model->DrawDebug(ent);
6364         }
6365 }
6366
6367 static void R_DrawModelsAddWaterPlanes(void)
6368 {
6369         int i;
6370         entity_render_t *ent;
6371
6372         for (i = 0;i < r_refdef.scene.numentities;i++)
6373         {
6374                 if (!r_refdef.viewcache.entityvisible[i])
6375                         continue;
6376                 ent = r_refdef.scene.entities[i];
6377                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
6378                         ent->model->DrawAddWaterPlanes(ent);
6379         }
6380 }
6381
6382 static void R_View_SetFrustum(void)
6383 {
6384         int i;
6385         double slopex, slopey;
6386         vec3_t forward, left, up, origin;
6387
6388         // we can't trust r_refdef.view.forward and friends in reflected scenes
6389         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
6390
6391 #if 0
6392         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
6393         r_refdef.view.frustum[0].normal[1] = 0 - 0;
6394         r_refdef.view.frustum[0].normal[2] = -1 - 0;
6395         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
6396         r_refdef.view.frustum[1].normal[1] = 0 + 0;
6397         r_refdef.view.frustum[1].normal[2] = -1 + 0;
6398         r_refdef.view.frustum[2].normal[0] = 0 - 0;
6399         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
6400         r_refdef.view.frustum[2].normal[2] = -1 - 0;
6401         r_refdef.view.frustum[3].normal[0] = 0 + 0;
6402         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
6403         r_refdef.view.frustum[3].normal[2] = -1 + 0;
6404 #endif
6405
6406 #if 0
6407         zNear = r_refdef.nearclip;
6408         nudge = 1.0 - 1.0 / (1<<23);
6409         r_refdef.view.frustum[4].normal[0] = 0 - 0;
6410         r_refdef.view.frustum[4].normal[1] = 0 - 0;
6411         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
6412         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
6413         r_refdef.view.frustum[5].normal[0] = 0 + 0;
6414         r_refdef.view.frustum[5].normal[1] = 0 + 0;
6415         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
6416         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
6417 #endif
6418
6419
6420
6421 #if 0
6422         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
6423         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
6424         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
6425         r_refdef.view.frustum[0].dist = m[15] - m[12];
6426
6427         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
6428         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
6429         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
6430         r_refdef.view.frustum[1].dist = m[15] + m[12];
6431
6432         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
6433         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
6434         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
6435         r_refdef.view.frustum[2].dist = m[15] - m[13];
6436
6437         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
6438         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
6439         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
6440         r_refdef.view.frustum[3].dist = m[15] + m[13];
6441
6442         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
6443         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
6444         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
6445         r_refdef.view.frustum[4].dist = m[15] - m[14];
6446
6447         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
6448         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
6449         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
6450         r_refdef.view.frustum[5].dist = m[15] + m[14];
6451 #endif
6452
6453         if (r_refdef.view.useperspective)
6454         {
6455                 slopex = 1.0 / r_refdef.view.frustum_x;
6456                 slopey = 1.0 / r_refdef.view.frustum_y;
6457                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
6458                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
6459                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
6460                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
6461                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6462
6463                 // Leaving those out was a mistake, those were in the old code, and they
6464                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
6465                 // I couldn't reproduce it after adding those normalizations. --blub
6466                 VectorNormalize(r_refdef.view.frustum[0].normal);
6467                 VectorNormalize(r_refdef.view.frustum[1].normal);
6468                 VectorNormalize(r_refdef.view.frustum[2].normal);
6469                 VectorNormalize(r_refdef.view.frustum[3].normal);
6470
6471                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
6472                 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]);
6473                 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]);
6474                 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]);
6475                 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]);
6476
6477                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
6478                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
6479                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
6480                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
6481                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6482         }
6483         else
6484         {
6485                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
6486                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
6487                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
6488                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
6489                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6490                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
6491                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
6492                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
6493                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
6494                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6495         }
6496         r_refdef.view.numfrustumplanes = 5;
6497
6498         if (r_refdef.view.useclipplane)
6499         {
6500                 r_refdef.view.numfrustumplanes = 6;
6501                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
6502         }
6503
6504         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6505                 PlaneClassify(r_refdef.view.frustum + i);
6506
6507         // LordHavoc: note to all quake engine coders, Quake had a special case
6508         // for 90 degrees which assumed a square view (wrong), so I removed it,
6509         // Quake2 has it disabled as well.
6510
6511         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
6512         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
6513         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
6514         //PlaneClassify(&frustum[0]);
6515
6516         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
6517         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
6518         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
6519         //PlaneClassify(&frustum[1]);
6520
6521         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
6522         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
6523         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
6524         //PlaneClassify(&frustum[2]);
6525
6526         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
6527         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
6528         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
6529         //PlaneClassify(&frustum[3]);
6530
6531         // nearclip plane
6532         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
6533         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
6534         //PlaneClassify(&frustum[4]);
6535 }
6536
6537 void R_View_Update(void)
6538 {
6539         R_Main_ResizeViewCache();
6540         R_View_SetFrustum();
6541         R_View_WorldVisibility(r_refdef.view.useclipplane);
6542         R_View_UpdateEntityVisible();
6543         R_View_UpdateEntityLighting();
6544 }
6545
6546 void R_SetupView(qboolean allowwaterclippingplane)
6547 {
6548         const float *customclipplane = NULL;
6549         float plane[4];
6550         if (r_refdef.view.useclipplane && allowwaterclippingplane)
6551         {
6552                 // LordHavoc: couldn't figure out how to make this approach the
6553                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
6554                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
6555                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
6556                         dist = r_refdef.view.clipplane.dist;
6557                 plane[0] = r_refdef.view.clipplane.normal[0];
6558                 plane[1] = r_refdef.view.clipplane.normal[1];
6559                 plane[2] = r_refdef.view.clipplane.normal[2];
6560                 plane[3] = dist;
6561                 customclipplane = plane;
6562         }
6563
6564         if (!r_refdef.view.useperspective)
6565                 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);
6566         else if (vid.stencil && r_useinfinitefarclip.integer)
6567                 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);
6568         else
6569                 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);
6570         R_SetViewport(&r_refdef.view.viewport);
6571 }
6572
6573 void R_EntityMatrix(const matrix4x4_t *matrix)
6574 {
6575         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
6576         {
6577                 gl_modelmatrixchanged = false;
6578                 gl_modelmatrix = *matrix;
6579                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
6580                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
6581                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
6582                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
6583                 CHECKGLERROR
6584                 switch(vid.renderpath)
6585                 {
6586                 case RENDERPATH_GL20:
6587                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
6588                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
6589                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6590                         break;
6591                 case RENDERPATH_CGGL:
6592 #ifdef SUPPORTCG
6593                         CHECKCGERROR
6594                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
6595                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
6596                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6597 #endif
6598                         break;
6599                 case RENDERPATH_GL13:
6600                 case RENDERPATH_GL11:
6601                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6602                         break;
6603                 }
6604         }
6605 }
6606
6607 void R_ResetViewRendering2D(void)
6608 {
6609         r_viewport_t viewport;
6610         DrawQ_Finish();
6611
6612         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
6613         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);
6614         R_SetViewport(&viewport);
6615         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
6616         GL_Color(1, 1, 1, 1);
6617         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6618         GL_BlendFunc(GL_ONE, GL_ZERO);
6619         GL_AlphaTest(false);
6620         GL_ScissorTest(false);
6621         GL_DepthMask(false);
6622         GL_DepthRange(0, 1);
6623         GL_DepthTest(false);
6624         R_EntityMatrix(&identitymatrix);
6625         R_Mesh_ResetTextureState();
6626         GL_PolygonOffset(0, 0);
6627         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
6628         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6629         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
6630         qglStencilMask(~0);CHECKGLERROR
6631         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
6632         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
6633         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
6634 }
6635
6636 void R_ResetViewRendering3D(void)
6637 {
6638         DrawQ_Finish();
6639
6640         R_SetupView(true);
6641         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6642         GL_Color(1, 1, 1, 1);
6643         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6644         GL_BlendFunc(GL_ONE, GL_ZERO);
6645         GL_AlphaTest(false);
6646         GL_ScissorTest(true);
6647         GL_DepthMask(true);
6648         GL_DepthRange(0, 1);
6649         GL_DepthTest(true);
6650         R_EntityMatrix(&identitymatrix);
6651         R_Mesh_ResetTextureState();
6652         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6653         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
6654         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6655         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
6656         qglStencilMask(~0);CHECKGLERROR
6657         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
6658         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
6659         GL_CullFace(r_refdef.view.cullface_back);
6660 }
6661
6662 void R_RenderScene(void);
6663 void R_RenderWaterPlanes(void);
6664
6665 static void R_Water_StartFrame(void)
6666 {
6667         int i;
6668         int waterwidth, waterheight, texturewidth, textureheight;
6669         r_waterstate_waterplane_t *p;
6670
6671         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
6672                 return;
6673
6674         switch(vid.renderpath)
6675         {
6676         case RENDERPATH_GL20:
6677         case RENDERPATH_CGGL:
6678                 break;
6679         case RENDERPATH_GL13:
6680         case RENDERPATH_GL11:
6681                 return;
6682         }
6683
6684         // set waterwidth and waterheight to the water resolution that will be
6685         // used (often less than the screen resolution for faster rendering)
6686         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
6687         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
6688
6689         // calculate desired texture sizes
6690         // can't use water if the card does not support the texture size
6691         if (!r_water.integer || r_showsurfaces.integer)
6692                 texturewidth = textureheight = waterwidth = waterheight = 0;
6693         else if (vid.support.arb_texture_non_power_of_two)
6694         {
6695                 texturewidth = waterwidth;
6696                 textureheight = waterheight;
6697         }
6698         else
6699         {
6700                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
6701                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
6702         }
6703
6704         // allocate textures as needed
6705         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
6706         {
6707                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
6708                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
6709                 {
6710                         if (p->texture_refraction)
6711                                 R_FreeTexture(p->texture_refraction);
6712                         p->texture_refraction = NULL;
6713                         if (p->texture_reflection)
6714                                 R_FreeTexture(p->texture_reflection);
6715                         p->texture_reflection = NULL;
6716                 }
6717                 memset(&r_waterstate, 0, sizeof(r_waterstate));
6718                 r_waterstate.texturewidth = texturewidth;
6719                 r_waterstate.textureheight = textureheight;
6720         }
6721
6722         if (r_waterstate.texturewidth)
6723         {
6724                 r_waterstate.enabled = true;
6725
6726                 // when doing a reduced render (HDR) we want to use a smaller area
6727                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
6728                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
6729
6730                 // set up variables that will be used in shader setup
6731                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
6732                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
6733                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
6734                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
6735         }
6736
6737         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
6738         r_waterstate.numwaterplanes = 0;
6739 }
6740
6741 void R_Water_AddWaterPlane(msurface_t *surface)
6742 {
6743         int triangleindex, planeindex;
6744         const int *e;
6745         vec3_t vert[3];
6746         vec3_t normal;
6747         vec3_t center;
6748         mplane_t plane;
6749         r_waterstate_waterplane_t *p;
6750         texture_t *t = R_GetCurrentTexture(surface->texture);
6751         // just use the first triangle with a valid normal for any decisions
6752         VectorClear(normal);
6753         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
6754         {
6755                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
6756                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
6757                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
6758                 TriangleNormal(vert[0], vert[1], vert[2], normal);
6759                 if (VectorLength2(normal) >= 0.001)
6760                         break;
6761         }
6762
6763         VectorCopy(normal, plane.normal);
6764         VectorNormalize(plane.normal);
6765         plane.dist = DotProduct(vert[0], plane.normal);
6766         PlaneClassify(&plane);
6767         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
6768         {
6769                 // skip backfaces (except if nocullface is set)
6770                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
6771                         return;
6772                 VectorNegate(plane.normal, plane.normal);
6773                 plane.dist *= -1;
6774                 PlaneClassify(&plane);
6775         }
6776
6777
6778         // find a matching plane if there is one
6779         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6780                 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
6781                         break;
6782         if (planeindex >= r_waterstate.maxwaterplanes)
6783                 return; // nothing we can do, out of planes
6784
6785         // if this triangle does not fit any known plane rendered this frame, add one
6786         if (planeindex >= r_waterstate.numwaterplanes)
6787         {
6788                 // store the new plane
6789                 r_waterstate.numwaterplanes++;
6790                 p->plane = plane;
6791                 // clear materialflags and pvs
6792                 p->materialflags = 0;
6793                 p->pvsvalid = false;
6794         }
6795         // merge this surface's materialflags into the waterplane
6796         p->materialflags |= t->currentmaterialflags;
6797         // merge this surface's PVS into the waterplane
6798         VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
6799         if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6800          && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6801         {
6802                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6803                 p->pvsvalid = true;
6804         }
6805 }
6806
6807 static void R_Water_ProcessPlanes(void)
6808 {
6809         r_refdef_view_t originalview;
6810         r_refdef_view_t myview;
6811         int planeindex;
6812         r_waterstate_waterplane_t *p;
6813
6814         originalview = r_refdef.view;
6815
6816         // make sure enough textures are allocated
6817         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6818         {
6819                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6820                 {
6821                         if (!p->texture_refraction)
6822                                 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
6823                         if (!p->texture_refraction)
6824                                 goto error;
6825                 }
6826
6827                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6828                 {
6829                         if (!p->texture_reflection)
6830                                 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
6831                         if (!p->texture_reflection)
6832                                 goto error;
6833                 }
6834         }
6835
6836         // render views
6837         r_refdef.view = originalview;
6838         r_refdef.view.showdebug = false;
6839         r_refdef.view.width = r_waterstate.waterwidth;
6840         r_refdef.view.height = r_waterstate.waterheight;
6841         r_refdef.view.useclipplane = true;
6842         myview = r_refdef.view;
6843         r_waterstate.renderingscene = true;
6844         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6845         {
6846                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6847                 {
6848                         r_refdef.view = myview;
6849                         // render reflected scene and copy into texture
6850                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6851                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6852                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6853                         r_refdef.view.clipplane = p->plane;
6854                         // reverse the cullface settings for this render
6855                         r_refdef.view.cullface_front = GL_FRONT;
6856                         r_refdef.view.cullface_back = GL_BACK;
6857                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6858                         {
6859                                 r_refdef.view.usecustompvs = true;
6860                                 if (p->pvsvalid)
6861                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6862                                 else
6863                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6864                         }
6865
6866                         R_ResetViewRendering3D();
6867                         R_ClearScreen(r_refdef.fogenabled);
6868                         R_View_Update();
6869                         R_RenderScene();
6870
6871                         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);
6872                 }
6873
6874                 // render the normal view scene and copy into texture
6875                 // (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)
6876                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6877                 {
6878                         r_refdef.view = myview;
6879                         r_refdef.view.clipplane = p->plane;
6880                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6881                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6882                         PlaneClassify(&r_refdef.view.clipplane);
6883
6884                         R_ResetViewRendering3D();
6885                         R_ClearScreen(r_refdef.fogenabled);
6886                         R_View_Update();
6887                         R_RenderScene();
6888
6889                         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);
6890                 }
6891
6892         }
6893         r_waterstate.renderingscene = false;
6894         r_refdef.view = originalview;
6895         R_ResetViewRendering3D();
6896         R_ClearScreen(r_refdef.fogenabled);
6897         R_View_Update();
6898         return;
6899 error:
6900         r_refdef.view = originalview;
6901         r_waterstate.renderingscene = false;
6902         Cvar_SetValueQuick(&r_water, 0);
6903         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6904         return;
6905 }
6906
6907 void R_Bloom_StartFrame(void)
6908 {
6909         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6910
6911         switch(vid.renderpath)
6912         {
6913         case RENDERPATH_GL20:
6914         case RENDERPATH_CGGL:
6915                 break;
6916         case RENDERPATH_GL13:
6917         case RENDERPATH_GL11:
6918                 return;
6919         }
6920
6921         // set bloomwidth and bloomheight to the bloom resolution that will be
6922         // used (often less than the screen resolution for faster rendering)
6923         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
6924         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
6925         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
6926         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
6927         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
6928
6929         // calculate desired texture sizes
6930         if (vid.support.arb_texture_non_power_of_two)
6931         {
6932                 screentexturewidth = r_refdef.view.width;
6933                 screentextureheight = r_refdef.view.height;
6934                 bloomtexturewidth = r_bloomstate.bloomwidth;
6935                 bloomtextureheight = r_bloomstate.bloomheight;
6936         }
6937         else
6938         {
6939                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
6940                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
6941                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
6942                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
6943         }
6944
6945         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))
6946         {
6947                 Cvar_SetValueQuick(&r_hdr, 0);
6948                 Cvar_SetValueQuick(&r_bloom, 0);
6949                 Cvar_SetValueQuick(&r_motionblur, 0);
6950                 Cvar_SetValueQuick(&r_damageblur, 0);
6951         }
6952
6953         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)))
6954                 screentexturewidth = screentextureheight = 0;
6955         if (!r_hdr.integer && !r_bloom.integer)
6956                 bloomtexturewidth = bloomtextureheight = 0;
6957
6958         // allocate textures as needed
6959         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
6960         {
6961                 if (r_bloomstate.texture_screen)
6962                         R_FreeTexture(r_bloomstate.texture_screen);
6963                 r_bloomstate.texture_screen = NULL;
6964                 r_bloomstate.screentexturewidth = screentexturewidth;
6965                 r_bloomstate.screentextureheight = screentextureheight;
6966                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
6967                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
6968         }
6969         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
6970         {
6971                 if (r_bloomstate.texture_bloom)
6972                         R_FreeTexture(r_bloomstate.texture_bloom);
6973                 r_bloomstate.texture_bloom = NULL;
6974                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6975                 r_bloomstate.bloomtextureheight = bloomtextureheight;
6976                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6977                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
6978         }
6979
6980         // when doing a reduced render (HDR) we want to use a smaller area
6981         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6982         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6983         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6984         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6985         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6986
6987         // set up a texcoord array for the full resolution screen image
6988         // (we have to keep this around to copy back during final render)
6989         r_bloomstate.screentexcoord2f[0] = 0;
6990         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
6991         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
6992         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
6993         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
6994         r_bloomstate.screentexcoord2f[5] = 0;
6995         r_bloomstate.screentexcoord2f[6] = 0;
6996         r_bloomstate.screentexcoord2f[7] = 0;
6997
6998         // set up a texcoord array for the reduced resolution bloom image
6999         // (which will be additive blended over the screen image)
7000         r_bloomstate.bloomtexcoord2f[0] = 0;
7001         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7002         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7003         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7004         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7005         r_bloomstate.bloomtexcoord2f[5] = 0;
7006         r_bloomstate.bloomtexcoord2f[6] = 0;
7007         r_bloomstate.bloomtexcoord2f[7] = 0;
7008
7009         if (r_hdr.integer || r_bloom.integer)
7010         {
7011                 r_bloomstate.enabled = true;
7012                 r_bloomstate.hdr = r_hdr.integer != 0;
7013         }
7014
7015         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);
7016 }
7017
7018 void R_Bloom_CopyBloomTexture(float colorscale)
7019 {
7020         r_refdef.stats.bloom++;
7021
7022         // scale down screen texture to the bloom texture size
7023         CHECKGLERROR
7024         R_SetViewport(&r_bloomstate.viewport);
7025         GL_BlendFunc(GL_ONE, GL_ZERO);
7026         GL_Color(colorscale, colorscale, colorscale, 1);
7027         // TODO: optimize with multitexture or GLSL
7028         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7029         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7030         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7031         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7032
7033         // we now have a bloom image in the framebuffer
7034         // copy it into the bloom image texture for later processing
7035         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);
7036         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7037 }
7038
7039 void R_Bloom_CopyHDRTexture(void)
7040 {
7041         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);
7042         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7043 }
7044
7045 void R_Bloom_MakeTexture(void)
7046 {
7047         int x, range, dir;
7048         float xoffset, yoffset, r, brighten;
7049
7050         r_refdef.stats.bloom++;
7051
7052         R_ResetViewRendering2D();
7053         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7054         R_Mesh_ColorPointer(NULL, 0, 0);
7055
7056         // we have a bloom image in the framebuffer
7057         CHECKGLERROR
7058         R_SetViewport(&r_bloomstate.viewport);
7059
7060         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
7061         {
7062                 x *= 2;
7063                 r = bound(0, r_bloom_colorexponent.value / x, 1);
7064                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7065                 GL_Color(r, r, r, 1);
7066                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7067                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7068                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7069                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7070
7071                 // copy the vertically blurred bloom view to a texture
7072                 GL_ActiveTexture(0);
7073                 CHECKGLERROR
7074                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
7075                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7076         }
7077
7078         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
7079         brighten = r_bloom_brighten.value;
7080         if (r_hdr.integer)
7081                 brighten *= r_hdr_range.value;
7082         brighten = sqrt(brighten);
7083         if(range >= 1)
7084                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
7085         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7086         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
7087
7088         for (dir = 0;dir < 2;dir++)
7089         {
7090                 // blend on at multiple vertical offsets to achieve a vertical blur
7091                 // TODO: do offset blends using GLSL
7092                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
7093                 GL_BlendFunc(GL_ONE, GL_ZERO);
7094                 for (x = -range;x <= range;x++)
7095                 {
7096                         if (!dir){xoffset = 0;yoffset = x;}
7097                         else {xoffset = x;yoffset = 0;}
7098                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
7099                         yoffset /= (float)r_bloomstate.bloomtextureheight;
7100                         // compute a texcoord array with the specified x and y offset
7101                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
7102                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7103                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7104                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7105                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7106                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
7107                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
7108                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
7109                         // this r value looks like a 'dot' particle, fading sharply to
7110                         // black at the edges
7111                         // (probably not realistic but looks good enough)
7112                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
7113                         //r = brighten/(range*2+1);
7114                         r = brighten / (range * 2 + 1);
7115                         if(range >= 1)
7116                                 r *= (1 - x*x/(float)(range*range));
7117                         GL_Color(r, r, r, 1);
7118                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7119                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7120                         GL_BlendFunc(GL_ONE, GL_ONE);
7121                 }
7122
7123                 // copy the vertically blurred bloom view to a texture
7124                 GL_ActiveTexture(0);
7125                 CHECKGLERROR
7126                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
7127                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7128         }
7129
7130         // apply subtract last
7131         // (just like it would be in a GLSL shader)
7132         if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
7133         {
7134                 GL_BlendFunc(GL_ONE, GL_ZERO);
7135                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7136                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7137                 GL_Color(1, 1, 1, 1);
7138                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7139                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7140
7141                 GL_BlendFunc(GL_ONE, GL_ONE);
7142                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
7143                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7144                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7145                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
7146                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7147                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7148                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
7149
7150                 // copy the darkened bloom view to a texture
7151                 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);
7152                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7153         }
7154 }
7155
7156 void R_HDR_RenderBloomTexture(void)
7157 {
7158         int oldwidth, oldheight;
7159         float oldcolorscale;
7160
7161         oldcolorscale = r_refdef.view.colorscale;
7162         oldwidth = r_refdef.view.width;
7163         oldheight = r_refdef.view.height;
7164         r_refdef.view.width = r_bloomstate.bloomwidth;
7165         r_refdef.view.height = r_bloomstate.bloomheight;
7166
7167         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
7168         // TODO: add exposure compensation features
7169         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
7170
7171         r_refdef.view.showdebug = false;
7172         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
7173
7174         R_ResetViewRendering3D();
7175
7176         R_ClearScreen(r_refdef.fogenabled);
7177         if (r_timereport_active)
7178                 R_TimeReport("HDRclear");
7179
7180         R_View_Update();
7181         if (r_timereport_active)
7182                 R_TimeReport("visibility");
7183
7184         // only do secondary renders with HDR if r_hdr is 2 or higher
7185         r_waterstate.numwaterplanes = 0;
7186         if (r_waterstate.enabled && r_hdr.integer >= 2)
7187                 R_RenderWaterPlanes();
7188
7189         r_refdef.view.showdebug = true;
7190         R_RenderScene();
7191         r_waterstate.numwaterplanes = 0;
7192
7193         R_ResetViewRendering2D();
7194
7195         R_Bloom_CopyHDRTexture();
7196         R_Bloom_MakeTexture();
7197
7198         // restore the view settings
7199         r_refdef.view.width = oldwidth;
7200         r_refdef.view.height = oldheight;
7201         r_refdef.view.colorscale = oldcolorscale;
7202         r_frame++; // used only by R_GetCurrentTexture
7203
7204         R_ResetViewRendering3D();
7205
7206         R_ClearScreen(r_refdef.fogenabled);
7207         if (r_timereport_active)
7208                 R_TimeReport("viewclear");
7209 }
7210
7211 static void R_BlendView(void)
7212 {
7213         unsigned int permutation;
7214         float uservecs[4][4];
7215
7216         switch (vid.renderpath)
7217         {
7218         case RENDERPATH_GL20:
7219         case RENDERPATH_CGGL:
7220                 permutation =
7221                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
7222                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
7223                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
7224                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
7225                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
7226
7227                 if (r_bloomstate.texture_screen)
7228                 {
7229                         // make sure the buffer is available
7230                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
7231
7232                         R_ResetViewRendering2D();
7233                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7234                         R_Mesh_ColorPointer(NULL, 0, 0);
7235
7236                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
7237                         {
7238                                 // declare variables
7239                                 float speed;
7240                                 static float avgspeed;
7241
7242                                 speed = VectorLength(cl.movement_velocity);
7243
7244                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
7245                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
7246
7247                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
7248                                 speed = bound(0, speed, 1);
7249                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
7250
7251                                 // calculate values into a standard alpha
7252                                 cl.motionbluralpha = 1 - exp(-
7253                                                 (
7254                                                  (r_motionblur.value * speed / 80)
7255                                                  +
7256                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
7257                                                 )
7258                                                 /
7259                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
7260                                            );
7261
7262                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
7263                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
7264                                 // apply the blur
7265                                 if (cl.motionbluralpha > 0)
7266                                 {
7267                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7268                                         GL_Color(1, 1, 1, cl.motionbluralpha);
7269                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7270                                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7271                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7272                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7273                                 }
7274                         }
7275
7276                         // copy view into the screen texture
7277                         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);
7278                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7279                 }
7280                 else if (!r_bloomstate.texture_bloom)
7281                 {
7282                         // we may still have to do view tint...
7283                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7284                         {
7285                                 // apply a color tint to the whole view
7286                                 R_ResetViewRendering2D();
7287                                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7288                                 R_Mesh_ColorPointer(NULL, 0, 0);
7289                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7290                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7291                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7292                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7293                         }
7294                         break; // no screen processing, no bloom, skip it
7295                 }
7296
7297                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
7298                 {
7299                         // render simple bloom effect
7300                         // copy the screen and shrink it and darken it for the bloom process
7301                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
7302                         // make the bloom texture
7303                         R_Bloom_MakeTexture();
7304                 }
7305
7306 #if _MSC_VER >= 1400
7307 #define sscanf sscanf_s
7308 #endif
7309                 memset(uservecs, 0, sizeof(uservecs));
7310                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
7311                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
7312                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
7313                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
7314
7315                 R_ResetViewRendering2D();
7316                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7317                 R_Mesh_ColorPointer(NULL, 0, 0);
7318                 GL_Color(1, 1, 1, 1);
7319                 GL_BlendFunc(GL_ONE, GL_ZERO);
7320                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7321                 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7322
7323                 switch(vid.renderpath)
7324                 {
7325                 case RENDERPATH_GL20:
7326                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
7327                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
7328                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
7329                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
7330                         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]);
7331                         if (r_glsl_permutation->loc_ClientTime         >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime        , cl.time);
7332                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
7333                         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]);
7334                         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]);
7335                         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]);
7336                         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]);
7337                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
7338                         break;
7339                 case RENDERPATH_CGGL:
7340 #ifdef SUPPORTCG
7341                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
7342                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
7343                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
7344                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
7345                         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
7346                         if (r_cg_permutation->fp_ClientTime        ) cgGLSetParameter1f(     r_cg_permutation->fp_ClientTime        , cl.time);CHECKCGERROR
7347                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
7348                         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
7349                         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
7350                         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
7351                         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
7352                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
7353 #endif
7354                         break;
7355                 default:
7356                         break;
7357                 }
7358                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7359                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7360                 break;
7361         case RENDERPATH_GL13:
7362         case RENDERPATH_GL11:
7363                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7364                 {
7365                         // apply a color tint to the whole view
7366                         R_ResetViewRendering2D();
7367                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7368                         R_Mesh_ColorPointer(NULL, 0, 0);
7369                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7370                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7371                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7372                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7373                 }
7374                 break;
7375         }
7376 }
7377
7378 matrix4x4_t r_waterscrollmatrix;
7379
7380 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
7381 {
7382         if (r_refdef.fog_density)
7383         {
7384                 r_refdef.fogcolor[0] = r_refdef.fog_red;
7385                 r_refdef.fogcolor[1] = r_refdef.fog_green;
7386                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7387
7388                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7389                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7390                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7391                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7392
7393                 {
7394                         vec3_t fogvec;
7395                         VectorCopy(r_refdef.fogcolor, fogvec);
7396                         //   color.rgb *= ContrastBoost * SceneBrightness;
7397                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7398                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7399                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7400                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7401                 }
7402         }
7403 }
7404
7405 void R_UpdateVariables(void)
7406 {
7407         R_Textures_Frame();
7408
7409         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7410
7411         r_refdef.farclip = r_farclip_base.value;
7412         if (r_refdef.scene.worldmodel)
7413                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7414         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7415
7416         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7417                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7418         r_refdef.polygonfactor = 0;
7419         r_refdef.polygonoffset = 0;
7420         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7421         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7422
7423         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7424         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7425         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
7426         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7427         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7428         if (r_showsurfaces.integer)
7429         {
7430                 r_refdef.scene.rtworld = false;
7431                 r_refdef.scene.rtworldshadows = false;
7432                 r_refdef.scene.rtdlight = false;
7433                 r_refdef.scene.rtdlightshadows = false;
7434                 r_refdef.lightmapintensity = 0;
7435         }
7436
7437         if (gamemode == GAME_NEHAHRA)
7438         {
7439                 if (gl_fogenable.integer)
7440                 {
7441                         r_refdef.oldgl_fogenable = true;
7442                         r_refdef.fog_density = gl_fogdensity.value;
7443                         r_refdef.fog_red = gl_fogred.value;
7444                         r_refdef.fog_green = gl_foggreen.value;
7445                         r_refdef.fog_blue = gl_fogblue.value;
7446                         r_refdef.fog_alpha = 1;
7447                         r_refdef.fog_start = 0;
7448                         r_refdef.fog_end = gl_skyclip.value;
7449                         r_refdef.fog_height = 1<<30;
7450                         r_refdef.fog_fadedepth = 128;
7451                 }
7452                 else if (r_refdef.oldgl_fogenable)
7453                 {
7454                         r_refdef.oldgl_fogenable = false;
7455                         r_refdef.fog_density = 0;
7456                         r_refdef.fog_red = 0;
7457                         r_refdef.fog_green = 0;
7458                         r_refdef.fog_blue = 0;
7459                         r_refdef.fog_alpha = 0;
7460                         r_refdef.fog_start = 0;
7461                         r_refdef.fog_end = 0;
7462                         r_refdef.fog_height = 1<<30;
7463                         r_refdef.fog_fadedepth = 128;
7464                 }
7465         }
7466
7467         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7468         r_refdef.fog_start = max(0, r_refdef.fog_start);
7469         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7470
7471         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
7472
7473         if (r_refdef.fog_density && r_drawfog.integer)
7474         {
7475                 r_refdef.fogenabled = true;
7476                 // this is the point where the fog reaches 0.9986 alpha, which we
7477                 // consider a good enough cutoff point for the texture
7478                 // (0.9986 * 256 == 255.6)
7479                 if (r_fog_exp2.integer)
7480                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7481                 else
7482                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7483                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7484                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7485                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7486                 // fog color was already set
7487                 // update the fog texture
7488                 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)
7489                         R_BuildFogTexture();
7490         }
7491         else
7492                 r_refdef.fogenabled = false;
7493
7494         switch(vid.renderpath)
7495         {
7496         case RENDERPATH_GL20:
7497         case RENDERPATH_CGGL:
7498                 if(v_glslgamma.integer && !vid_gammatables_trivial)
7499                 {
7500                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7501                         {
7502                                 // build GLSL gamma texture
7503 #define RAMPWIDTH 256
7504                                 unsigned short ramp[RAMPWIDTH * 3];
7505                                 unsigned char rampbgr[RAMPWIDTH][4];
7506                                 int i;
7507
7508                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7509
7510                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7511                                 for(i = 0; i < RAMPWIDTH; ++i)
7512                                 {
7513                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7514                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7515                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7516                                         rampbgr[i][3] = 0;
7517                                 }
7518                                 if (r_texture_gammaramps)
7519                                 {
7520                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
7521                                 }
7522                                 else
7523                                 {
7524                                         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);
7525                                 }
7526                         }
7527                 }
7528                 else
7529                 {
7530                         // remove GLSL gamma texture
7531                 }
7532                 break;
7533         case RENDERPATH_GL13:
7534         case RENDERPATH_GL11:
7535                 break;
7536         }
7537 }
7538
7539 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7540 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7541 /*
7542 ================
7543 R_SelectScene
7544 ================
7545 */
7546 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7547         if( scenetype != r_currentscenetype ) {
7548                 // store the old scenetype
7549                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7550                 r_currentscenetype = scenetype;
7551                 // move in the new scene
7552                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7553         }
7554 }
7555
7556 /*
7557 ================
7558 R_GetScenePointer
7559 ================
7560 */
7561 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7562 {
7563         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7564         if( scenetype == r_currentscenetype ) {
7565                 return &r_refdef.scene;
7566         } else {
7567                 return &r_scenes_store[ scenetype ];
7568         }
7569 }
7570
7571 /*
7572 ================
7573 R_RenderView
7574 ================
7575 */
7576 void R_RenderView(void)
7577 {
7578         if (r_timereport_active)
7579                 R_TimeReport("start");
7580         r_frame++; // used only by R_GetCurrentTexture
7581         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7582
7583         if (!r_drawentities.integer)
7584                 r_refdef.scene.numentities = 0;
7585
7586         R_AnimCache_ClearCache();
7587         R_FrameData_NewFrame();
7588
7589         if (r_refdef.view.isoverlay)
7590         {
7591                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7592                 GL_Clear( GL_DEPTH_BUFFER_BIT );
7593                 R_TimeReport("depthclear");
7594
7595                 r_refdef.view.showdebug = false;
7596
7597                 r_waterstate.enabled = false;
7598                 r_waterstate.numwaterplanes = 0;
7599
7600                 R_RenderScene();
7601
7602                 CHECKGLERROR
7603                 return;
7604         }
7605
7606         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
7607                 return; //Host_Error ("R_RenderView: NULL worldmodel");
7608
7609         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
7610
7611         // break apart the view matrix into vectors for various purposes
7612         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
7613         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
7614         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
7615         VectorNegate(r_refdef.view.left, r_refdef.view.right);
7616         // make an inverted copy of the view matrix for tracking sprites
7617         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
7618
7619         R_Shadow_UpdateWorldLightSelection();
7620
7621         R_Bloom_StartFrame();
7622         R_Water_StartFrame();
7623
7624         CHECKGLERROR
7625         if (r_timereport_active)
7626                 R_TimeReport("viewsetup");
7627
7628         R_ResetViewRendering3D();
7629
7630         if (r_refdef.view.clear || r_refdef.fogenabled)
7631         {
7632                 R_ClearScreen(r_refdef.fogenabled);
7633                 if (r_timereport_active)
7634                         R_TimeReport("viewclear");
7635         }
7636         r_refdef.view.clear = true;
7637
7638         // this produces a bloom texture to be used in R_BlendView() later
7639         if (r_hdr.integer && r_bloomstate.bloomwidth)
7640                 R_HDR_RenderBloomTexture();
7641
7642         r_refdef.view.showdebug = true;
7643
7644         R_View_Update();
7645         if (r_timereport_active)
7646                 R_TimeReport("visibility");
7647
7648         r_waterstate.numwaterplanes = 0;
7649         if (r_waterstate.enabled)
7650                 R_RenderWaterPlanes();
7651
7652         R_RenderScene();
7653         r_waterstate.numwaterplanes = 0;
7654
7655         R_BlendView();
7656         if (r_timereport_active)
7657                 R_TimeReport("blendview");
7658
7659         GL_Scissor(0, 0, vid.width, vid.height);
7660         GL_ScissorTest(false);
7661         CHECKGLERROR
7662 }
7663
7664 void R_RenderWaterPlanes(void)
7665 {
7666         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7667         {
7668                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7669                 if (r_timereport_active)
7670                         R_TimeReport("waterworld");
7671         }
7672
7673         // don't let sound skip if going slow
7674         if (r_refdef.scene.extraupdate)
7675                 S_ExtraUpdate ();
7676
7677         R_DrawModelsAddWaterPlanes();
7678         if (r_timereport_active)
7679                 R_TimeReport("watermodels");
7680
7681         if (r_waterstate.numwaterplanes)
7682         {
7683                 R_Water_ProcessPlanes();
7684                 if (r_timereport_active)
7685                         R_TimeReport("waterscenes");
7686         }
7687 }
7688
7689 extern void R_DrawLightningBeams (void);
7690 extern void VM_CL_AddPolygonsToMeshQueue (void);
7691 extern void R_DrawPortals (void);
7692 extern cvar_t cl_locs_show;
7693 static void R_DrawLocs(void);
7694 static void R_DrawEntityBBoxes(void);
7695 static void R_DrawModelDecals(void);
7696 extern cvar_t cl_decals_newsystem;
7697 extern qboolean r_shadow_usingdeferredprepass;
7698 void R_RenderScene(void)
7699 {
7700         r_refdef.stats.renders++;
7701
7702         R_UpdateFogColor();
7703
7704         // don't let sound skip if going slow
7705         if (r_refdef.scene.extraupdate)
7706                 S_ExtraUpdate ();
7707
7708         R_MeshQueue_BeginScene();
7709
7710         R_SkyStartFrame();
7711
7712         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);
7713
7714         if (cl.csqc_vidvars.drawworld)
7715         {
7716                 // don't let sound skip if going slow
7717                 if (r_refdef.scene.extraupdate)
7718                         S_ExtraUpdate ();
7719
7720                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7721                 {
7722                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7723                         if (r_timereport_active)
7724                                 R_TimeReport("worldsky");
7725                 }
7726
7727                 if (R_DrawBrushModelsSky() && r_timereport_active)
7728                         R_TimeReport("bmodelsky");
7729
7730                 if (skyrendermasked && skyrenderlater)
7731                 {
7732                         // we have to force off the water clipping plane while rendering sky
7733                         R_SetupView(false);
7734                         R_Sky();
7735                         R_SetupView(true);
7736                         if (r_timereport_active)
7737                                 R_TimeReport("sky");
7738                 }
7739         }
7740
7741         R_AnimCache_CacheVisibleEntities();
7742         if (r_timereport_active)
7743                 R_TimeReport("animation");
7744
7745         R_Shadow_PrepareLights();
7746         if (r_timereport_active)
7747                 R_TimeReport("preparelights");
7748
7749         if (r_shadow_usingdeferredprepass)
7750                 R_Shadow_DrawPrepass();
7751
7752         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7753         {
7754                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7755                 if (r_timereport_active)
7756                         R_TimeReport("worlddepth");
7757         }
7758         if (r_depthfirst.integer >= 2)
7759         {
7760                 R_DrawModelsDepth();
7761                 if (r_timereport_active)
7762                         R_TimeReport("modeldepth");
7763         }
7764
7765         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7766         {
7767                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7768                 if (r_timereport_active)
7769                         R_TimeReport("world");
7770         }
7771
7772         // don't let sound skip if going slow
7773         if (r_refdef.scene.extraupdate)
7774                 S_ExtraUpdate ();
7775
7776         R_DrawModels();
7777         if (r_timereport_active)
7778                 R_TimeReport("models");
7779
7780         // don't let sound skip if going slow
7781         if (r_refdef.scene.extraupdate)
7782                 S_ExtraUpdate ();
7783
7784         if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7785         {
7786                 R_DrawModelShadows();
7787                 R_ResetViewRendering3D();
7788                 // don't let sound skip if going slow
7789                 if (r_refdef.scene.extraupdate)
7790                         S_ExtraUpdate ();
7791         }
7792
7793         if (!r_shadow_usingdeferredprepass)
7794         {
7795                 R_Shadow_DrawLights();
7796                 if (r_timereport_active)
7797                         R_TimeReport("rtlights");
7798         }
7799
7800         // don't let sound skip if going slow
7801         if (r_refdef.scene.extraupdate)
7802                 S_ExtraUpdate ();
7803
7804         if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7805         {
7806                 R_DrawModelShadows();
7807                 R_ResetViewRendering3D();
7808                 // don't let sound skip if going slow
7809                 if (r_refdef.scene.extraupdate)
7810                         S_ExtraUpdate ();
7811         }
7812
7813         if (cl.csqc_vidvars.drawworld)
7814         {
7815                 if (cl_decals_newsystem.integer)
7816                 {
7817                         R_DrawModelDecals();
7818                         if (r_timereport_active)
7819                                 R_TimeReport("modeldecals");
7820                 }
7821                 else
7822                 {
7823                         R_DrawDecals();
7824                         if (r_timereport_active)
7825                                 R_TimeReport("decals");
7826                 }
7827
7828                 R_DrawParticles();
7829                 if (r_timereport_active)
7830                         R_TimeReport("particles");
7831
7832                 R_DrawExplosions();
7833                 if (r_timereport_active)
7834                         R_TimeReport("explosions");
7835
7836                 R_DrawLightningBeams();
7837                 if (r_timereport_active)
7838                         R_TimeReport("lightning");
7839         }
7840
7841         VM_CL_AddPolygonsToMeshQueue();
7842
7843         if (r_refdef.view.showdebug)
7844         {
7845                 if (cl_locs_show.integer)
7846                 {
7847                         R_DrawLocs();
7848                         if (r_timereport_active)
7849                                 R_TimeReport("showlocs");
7850                 }
7851
7852                 if (r_drawportals.integer)
7853                 {
7854                         R_DrawPortals();
7855                         if (r_timereport_active)
7856                                 R_TimeReport("portals");
7857                 }
7858
7859                 if (r_showbboxes.value > 0)
7860                 {
7861                         R_DrawEntityBBoxes();
7862                         if (r_timereport_active)
7863                                 R_TimeReport("bboxes");
7864                 }
7865         }
7866
7867         R_MeshQueue_RenderTransparent();
7868         if (r_timereport_active)
7869                 R_TimeReport("drawtrans");
7870
7871         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))
7872         {
7873                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7874                 if (r_timereport_active)
7875                         R_TimeReport("worlddebug");
7876                 R_DrawModelsDebug();
7877                 if (r_timereport_active)
7878                         R_TimeReport("modeldebug");
7879         }
7880
7881         if (cl.csqc_vidvars.drawworld)
7882         {
7883                 R_Shadow_DrawCoronas();
7884                 if (r_timereport_active)
7885                         R_TimeReport("coronas");
7886         }
7887
7888         // don't let sound skip if going slow
7889         if (r_refdef.scene.extraupdate)
7890                 S_ExtraUpdate ();
7891
7892         R_ResetViewRendering2D();
7893 }
7894
7895 static const unsigned short bboxelements[36] =
7896 {
7897         5, 1, 3, 5, 3, 7,
7898         6, 2, 0, 6, 0, 4,
7899         7, 3, 2, 7, 2, 6,
7900         4, 0, 1, 4, 1, 5,
7901         4, 5, 7, 4, 7, 6,
7902         1, 0, 2, 1, 2, 3,
7903 };
7904
7905 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7906 {
7907         int i;
7908         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7909
7910         RSurf_ActiveWorldEntity();
7911
7912         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7913         GL_DepthMask(false);
7914         GL_DepthRange(0, 1);
7915         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7916         R_Mesh_ResetTextureState();
7917
7918         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7919         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7920         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7921         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7922         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7923         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7924         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7925         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7926         R_FillColors(color4f, 8, cr, cg, cb, ca);
7927         if (r_refdef.fogenabled)
7928         {
7929                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7930                 {
7931                         f1 = RSurf_FogVertex(v);
7932                         f2 = 1 - f1;
7933                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7934                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7935                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7936                 }
7937         }
7938         R_Mesh_VertexPointer(vertex3f, 0, 0);
7939         R_Mesh_ColorPointer(color4f, 0, 0);
7940         R_Mesh_ResetTextureState();
7941         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7942         R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
7943 }
7944
7945 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7946 {
7947         int i;
7948         float color[4];
7949         prvm_edict_t *edict;
7950         prvm_prog_t *prog_save = prog;
7951
7952         // this function draws bounding boxes of server entities
7953         if (!sv.active)
7954                 return;
7955
7956         GL_CullFace(GL_NONE);
7957         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7958
7959         prog = 0;
7960         SV_VM_Begin();
7961         for (i = 0;i < numsurfaces;i++)
7962         {
7963                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7964                 switch ((int)edict->fields.server->solid)
7965                 {
7966                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7967                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7968                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7969                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7970                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7971                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7972                 }
7973                 color[3] *= r_showbboxes.value;
7974                 color[3] = bound(0, color[3], 1);
7975                 GL_DepthTest(!r_showdisabledepthtest.integer);
7976                 GL_CullFace(r_refdef.view.cullface_front);
7977                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7978         }
7979         SV_VM_End();
7980         prog = prog_save;
7981 }
7982
7983 static void R_DrawEntityBBoxes(void)
7984 {
7985         int i;
7986         prvm_edict_t *edict;
7987         vec3_t center;
7988         prvm_prog_t *prog_save = prog;
7989
7990         // this function draws bounding boxes of server entities
7991         if (!sv.active)
7992                 return;
7993
7994         prog = 0;
7995         SV_VM_Begin();
7996         for (i = 0;i < prog->num_edicts;i++)
7997         {
7998                 edict = PRVM_EDICT_NUM(i);
7999                 if (edict->priv.server->free)
8000                         continue;
8001                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
8002                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
8003                         continue;
8004                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
8005                         continue;
8006                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
8007                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
8008         }
8009         SV_VM_End();
8010         prog = prog_save;
8011 }
8012
8013 static const int nomodelelement3i[24] =
8014 {
8015         5, 2, 0,
8016         5, 1, 2,
8017         5, 0, 3,
8018         5, 3, 1,
8019         0, 2, 4,
8020         2, 1, 4,
8021         3, 0, 4,
8022         1, 3, 4
8023 };
8024
8025 static const unsigned short nomodelelement3s[24] =
8026 {
8027         5, 2, 0,
8028         5, 1, 2,
8029         5, 0, 3,
8030         5, 3, 1,
8031         0, 2, 4,
8032         2, 1, 4,
8033         3, 0, 4,
8034         1, 3, 4
8035 };
8036
8037 static const float nomodelvertex3f[6*3] =
8038 {
8039         -16,   0,   0,
8040          16,   0,   0,
8041           0, -16,   0,
8042           0,  16,   0,
8043           0,   0, -16,
8044           0,   0,  16
8045 };
8046
8047 static const float nomodelcolor4f[6*4] =
8048 {
8049         0.0f, 0.0f, 0.5f, 1.0f,
8050         0.0f, 0.0f, 0.5f, 1.0f,
8051         0.0f, 0.5f, 0.0f, 1.0f,
8052         0.0f, 0.5f, 0.0f, 1.0f,
8053         0.5f, 0.0f, 0.0f, 1.0f,
8054         0.5f, 0.0f, 0.0f, 1.0f
8055 };
8056
8057 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8058 {
8059         int i;
8060         float f1, f2, *c;
8061         float color4f[6*4];
8062
8063         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);
8064
8065         // this is only called once per entity so numsurfaces is always 1, and
8066         // surfacelist is always {0}, so this code does not handle batches
8067
8068         if (rsurface.ent_flags & RENDER_ADDITIVE)
8069         {
8070                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
8071                 GL_DepthMask(false);
8072         }
8073         else if (rsurface.colormod[3] < 1)
8074         {
8075                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8076                 GL_DepthMask(false);
8077         }
8078         else
8079         {
8080                 GL_BlendFunc(GL_ONE, GL_ZERO);
8081                 GL_DepthMask(true);
8082         }
8083         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8084         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8085         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8086         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8087         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8088         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
8089         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8090         R_Mesh_ColorPointer(color4f, 0, 0);
8091         for (i = 0, c = color4f;i < 6;i++, c += 4)
8092         {
8093                 c[0] *= rsurface.colormod[0];
8094                 c[1] *= rsurface.colormod[1];
8095                 c[2] *= rsurface.colormod[2];
8096                 c[3] *= rsurface.colormod[3];
8097         }
8098         if (r_refdef.fogenabled)
8099         {
8100                 for (i = 0, c = color4f;i < 6;i++, c += 4)
8101                 {
8102                         f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
8103                         f2 = 1 - f1;
8104                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8105                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8106                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8107                 }
8108         }
8109         R_Mesh_ResetTextureState();
8110         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
8111 }
8112
8113 void R_DrawNoModel(entity_render_t *ent)
8114 {
8115         vec3_t org;
8116         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8117         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8118                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8119         else
8120                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8121 }
8122
8123 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8124 {
8125         vec3_t right1, right2, diff, normal;
8126
8127         VectorSubtract (org2, org1, normal);
8128
8129         // calculate 'right' vector for start
8130         VectorSubtract (r_refdef.view.origin, org1, diff);
8131         CrossProduct (normal, diff, right1);
8132         VectorNormalize (right1);
8133
8134         // calculate 'right' vector for end
8135         VectorSubtract (r_refdef.view.origin, org2, diff);
8136         CrossProduct (normal, diff, right2);
8137         VectorNormalize (right2);
8138
8139         vert[ 0] = org1[0] + width * right1[0];
8140         vert[ 1] = org1[1] + width * right1[1];
8141         vert[ 2] = org1[2] + width * right1[2];
8142         vert[ 3] = org1[0] - width * right1[0];
8143         vert[ 4] = org1[1] - width * right1[1];
8144         vert[ 5] = org1[2] - width * right1[2];
8145         vert[ 6] = org2[0] - width * right2[0];
8146         vert[ 7] = org2[1] - width * right2[1];
8147         vert[ 8] = org2[2] - width * right2[2];
8148         vert[ 9] = org2[0] + width * right2[0];
8149         vert[10] = org2[1] + width * right2[1];
8150         vert[11] = org2[2] + width * right2[2];
8151 }
8152
8153 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)
8154 {
8155         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8156         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8157         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8158         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8159         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8160         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8161         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8162         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8163         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8164         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8165         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8166         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8167 }
8168
8169 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8170 {
8171         int i;
8172         float *vertex3f;
8173         float v[3];
8174         VectorSet(v, x, y, z);
8175         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8176                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8177                         break;
8178         if (i == mesh->numvertices)
8179         {
8180                 if (mesh->numvertices < mesh->maxvertices)
8181                 {
8182                         VectorCopy(v, vertex3f);
8183                         mesh->numvertices++;
8184                 }
8185                 return mesh->numvertices;
8186         }
8187         else
8188                 return i;
8189 }
8190
8191 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8192 {
8193         int i;
8194         int *e, element[3];
8195         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8196         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8197         e = mesh->element3i + mesh->numtriangles * 3;
8198         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8199         {
8200                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8201                 if (mesh->numtriangles < mesh->maxtriangles)
8202                 {
8203                         *e++ = element[0];
8204                         *e++ = element[1];
8205                         *e++ = element[2];
8206                         mesh->numtriangles++;
8207                 }
8208                 element[1] = element[2];
8209         }
8210 }
8211
8212 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8213 {
8214         int i;
8215         int *e, element[3];
8216         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8217         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8218         e = mesh->element3i + mesh->numtriangles * 3;
8219         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8220         {
8221                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8222                 if (mesh->numtriangles < mesh->maxtriangles)
8223                 {
8224                         *e++ = element[0];
8225                         *e++ = element[1];
8226                         *e++ = element[2];
8227                         mesh->numtriangles++;
8228                 }
8229                 element[1] = element[2];
8230         }
8231 }
8232
8233 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8234 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8235 {
8236         int planenum, planenum2;
8237         int w;
8238         int tempnumpoints;
8239         mplane_t *plane, *plane2;
8240         double maxdist;
8241         double temppoints[2][256*3];
8242         // figure out how large a bounding box we need to properly compute this brush
8243         maxdist = 0;
8244         for (w = 0;w < numplanes;w++)
8245                 maxdist = max(maxdist, fabs(planes[w].dist));
8246         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8247         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8248         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8249         {
8250                 w = 0;
8251                 tempnumpoints = 4;
8252                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8253                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8254                 {
8255                         if (planenum2 == planenum)
8256                                 continue;
8257                         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);
8258                         w = !w;
8259                 }
8260                 if (tempnumpoints < 3)
8261                         continue;
8262                 // generate elements forming a triangle fan for this polygon
8263                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8264         }
8265 }
8266
8267 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)
8268 {
8269         texturelayer_t *layer;
8270         layer = t->currentlayers + t->currentnumlayers++;
8271         layer->type = type;
8272         layer->depthmask = depthmask;
8273         layer->blendfunc1 = blendfunc1;
8274         layer->blendfunc2 = blendfunc2;
8275         layer->texture = texture;
8276         layer->texmatrix = *matrix;
8277         layer->color[0] = r;
8278         layer->color[1] = g;
8279         layer->color[2] = b;
8280         layer->color[3] = a;
8281 }
8282
8283 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8284 {
8285         double index, f;
8286         index = parms[2] + r_refdef.scene.time * parms[3];
8287         index -= floor(index);
8288         switch (func)
8289         {
8290         default:
8291         case Q3WAVEFUNC_NONE:
8292         case Q3WAVEFUNC_NOISE:
8293         case Q3WAVEFUNC_COUNT:
8294                 f = 0;
8295                 break;
8296         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8297         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8298         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8299         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8300         case Q3WAVEFUNC_TRIANGLE:
8301                 index *= 4;
8302                 f = index - floor(index);
8303                 if (index < 1)
8304                         f = f;
8305                 else if (index < 2)
8306                         f = 1 - f;
8307                 else if (index < 3)
8308                         f = -f;
8309                 else
8310                         f = -(1 - f);
8311                 break;
8312         }
8313         return (float)(parms[0] + parms[1] * f);
8314 }
8315
8316 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8317 {
8318         int w, h, idx;
8319         float f;
8320         float tcmat[12];
8321         matrix4x4_t matrix, temp;
8322         switch(tcmod->tcmod)
8323         {
8324                 case Q3TCMOD_COUNT:
8325                 case Q3TCMOD_NONE:
8326                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8327                                 matrix = r_waterscrollmatrix;
8328                         else
8329                                 matrix = identitymatrix;
8330                         break;
8331                 case Q3TCMOD_ENTITYTRANSLATE:
8332                         // this is used in Q3 to allow the gamecode to control texcoord
8333                         // scrolling on the entity, which is not supported in darkplaces yet.
8334                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8335                         break;
8336                 case Q3TCMOD_ROTATE:
8337                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8338                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
8339                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8340                         break;
8341                 case Q3TCMOD_SCALE:
8342                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8343                         break;
8344                 case Q3TCMOD_SCROLL:
8345                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
8346                         break;
8347                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8348                         w = (int) tcmod->parms[0];
8349                         h = (int) tcmod->parms[1];
8350                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
8351                         f = f - floor(f);
8352                         idx = (int) floor(f * w * h);
8353                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8354                         break;
8355                 case Q3TCMOD_STRETCH:
8356                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8357                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8358                         break;
8359                 case Q3TCMOD_TRANSFORM:
8360                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8361                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8362                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8363                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8364                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8365                         break;
8366                 case Q3TCMOD_TURBULENT:
8367                         // this is handled in the RSurf_PrepareVertices function
8368                         matrix = identitymatrix;
8369                         break;
8370         }
8371         temp = *texmatrix;
8372         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8373 }
8374
8375 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8376 {
8377         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
8378         char name[MAX_QPATH];
8379         skinframe_t *skinframe;
8380         unsigned char pixels[296*194];
8381         strlcpy(cache->name, skinname, sizeof(cache->name));
8382         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8383         if (developer_loading.integer)
8384                 Con_Printf("loading %s\n", name);
8385         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8386         if (!skinframe || !skinframe->base)
8387         {
8388                 unsigned char *f;
8389                 fs_offset_t filesize;
8390                 skinframe = NULL;
8391                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8392                 if (f)
8393                 {
8394                         if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
8395                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8396                         Mem_Free(f);
8397                 }
8398         }
8399         cache->skinframe = skinframe;
8400 }
8401
8402 texture_t *R_GetCurrentTexture(texture_t *t)
8403 {
8404         int i;
8405         const entity_render_t *ent = rsurface.entity;
8406         dp_model_t *model = ent->model;
8407         q3shaderinfo_layer_tcmod_t *tcmod;
8408
8409         if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
8410                 return t->currentframe;
8411         t->update_lastrenderframe = r_frame;
8412         t->update_lastrenderentity = (void *)ent;
8413
8414         // switch to an alternate material if this is a q1bsp animated material
8415         {
8416                 texture_t *texture = t;
8417                 int s = rsurface.ent_skinnum;
8418                 if ((unsigned int)s >= (unsigned int)model->numskins)
8419                         s = 0;
8420                 if (model->skinscenes)
8421                 {
8422                         if (model->skinscenes[s].framecount > 1)
8423                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8424                         else
8425                                 s = model->skinscenes[s].firstframe;
8426                 }
8427                 if (s > 0)
8428                         t = t + s * model->num_surfaces;
8429                 if (t->animated)
8430                 {
8431                         // use an alternate animation if the entity's frame is not 0,
8432                         // and only if the texture has an alternate animation
8433                         if (rsurface.ent_alttextures && t->anim_total[1])
8434                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
8435                         else
8436                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
8437                 }
8438                 texture->currentframe = t;
8439         }
8440
8441         // update currentskinframe to be a qw skin or animation frame
8442         if (rsurface.ent_qwskin >= 0)
8443         {
8444                 i = rsurface.ent_qwskin;
8445                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8446                 {
8447                         r_qwskincache_size = cl.maxclients;
8448                         if (r_qwskincache)
8449                                 Mem_Free(r_qwskincache);
8450                         r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8451                 }
8452                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8453                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8454                 t->currentskinframe = r_qwskincache[i].skinframe;
8455                 if (t->currentskinframe == NULL)
8456                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8457         }
8458         else if (t->numskinframes >= 2)
8459                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8460         if (t->backgroundnumskinframes >= 2)
8461                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
8462
8463         t->currentmaterialflags = t->basematerialflags;
8464         t->currentalpha = rsurface.colormod[3];
8465         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
8466                 t->currentalpha *= r_wateralpha.value;
8467         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
8468                 t->currentalpha *= t->r_water_wateralpha;
8469         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
8470                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
8471         if (!(rsurface.ent_flags & RENDER_LIGHT))
8472                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8473         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8474         {
8475                 // pick a model lighting mode
8476                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8477                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8478                 else
8479                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8480         }
8481         if (rsurface.ent_flags & RENDER_ADDITIVE)
8482                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8483         else if (t->currentalpha < 1)
8484                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8485         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8486                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8487         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8488                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8489         if (t->backgroundnumskinframes)
8490                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8491         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8492         {
8493                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
8494                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8495         }
8496         else
8497                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
8498         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8499                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8500
8501         // there is no tcmod
8502         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8503         {
8504                 t->currenttexmatrix = r_waterscrollmatrix;
8505                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8506         }
8507         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8508         {
8509                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8510                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8511         }
8512
8513         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8514                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8515         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8516                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8517
8518         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8519         if (t->currentskinframe->qpixels)
8520                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8521         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8522         if (!t->basetexture)
8523                 t->basetexture = r_texture_notexture;
8524         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8525         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8526         t->nmaptexture = t->currentskinframe->nmap;
8527         if (!t->nmaptexture)
8528                 t->nmaptexture = r_texture_blanknormalmap;
8529         t->glosstexture = r_texture_black;
8530         t->glowtexture = t->currentskinframe->glow;
8531         t->fogtexture = t->currentskinframe->fog;
8532         if (t->backgroundnumskinframes)
8533         {
8534                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8535                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8536                 t->backgroundglosstexture = r_texture_black;
8537                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8538                 if (!t->backgroundnmaptexture)
8539                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8540         }
8541         else
8542         {
8543                 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
8544                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8545                 t->backgroundglosstexture = r_texture_black;
8546                 t->backgroundglowtexture = NULL;
8547         }
8548         t->specularpower = r_shadow_glossexponent.value;
8549         // TODO: store reference values for these in the texture?
8550         t->specularscale = 0;
8551         if (r_shadow_gloss.integer > 0)
8552         {
8553                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8554                 {
8555                         if (r_shadow_glossintensity.value > 0)
8556                         {
8557                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8558                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8559                                 t->specularscale = r_shadow_glossintensity.value;
8560                         }
8561                 }
8562                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8563                 {
8564                         t->glosstexture = r_texture_white;
8565                         t->backgroundglosstexture = r_texture_white;
8566                         t->specularscale = r_shadow_gloss2intensity.value;
8567                         t->specularpower = r_shadow_gloss2exponent.value;
8568                 }
8569         }
8570         t->specularscale *= t->specularscalemod;
8571         t->specularpower *= t->specularpowermod;
8572
8573         // lightmaps mode looks bad with dlights using actual texturing, so turn
8574         // off the colormap and glossmap, but leave the normalmap on as it still
8575         // accurately represents the shading involved
8576         if (gl_lightmaps.integer)
8577         {
8578                 t->basetexture = r_texture_grey128;
8579                 t->pantstexture = r_texture_black;
8580                 t->shirttexture = r_texture_black;
8581                 t->nmaptexture = r_texture_blanknormalmap;
8582                 t->glosstexture = r_texture_black;
8583                 t->glowtexture = NULL;
8584                 t->fogtexture = NULL;
8585                 t->backgroundbasetexture = NULL;
8586                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8587                 t->backgroundglosstexture = r_texture_black;
8588                 t->backgroundglowtexture = NULL;
8589                 t->specularscale = 0;
8590                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8591         }
8592
8593         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8594         VectorClear(t->dlightcolor);
8595         t->currentnumlayers = 0;
8596         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8597         {
8598                 int blendfunc1, blendfunc2;
8599                 qboolean depthmask;
8600                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8601                 {
8602                         blendfunc1 = GL_SRC_ALPHA;
8603                         blendfunc2 = GL_ONE;
8604                 }
8605                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8606                 {
8607                         blendfunc1 = GL_SRC_ALPHA;
8608                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8609                 }
8610                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8611                 {
8612                         blendfunc1 = t->customblendfunc[0];
8613                         blendfunc2 = t->customblendfunc[1];
8614                 }
8615                 else
8616                 {
8617                         blendfunc1 = GL_ONE;
8618                         blendfunc2 = GL_ZERO;
8619                 }
8620                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8621                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8622                 {
8623                         // fullbright is not affected by r_refdef.lightmapintensity
8624                         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]);
8625                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8626                                 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]);
8627                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8628                                 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]);
8629                 }
8630                 else
8631                 {
8632                         vec3_t ambientcolor;
8633                         float colorscale;
8634                         // set the color tint used for lights affecting this surface
8635                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8636                         colorscale = 2;
8637                         // q3bsp has no lightmap updates, so the lightstylevalue that
8638                         // would normally be baked into the lightmap must be
8639                         // applied to the color
8640                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8641                         if (model->type == mod_brushq3)
8642                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8643                         colorscale *= r_refdef.lightmapintensity;
8644                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8645                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8646                         // basic lit geometry
8647                         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]);
8648                         // add pants/shirt if needed
8649                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8650                                 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]);
8651                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8652                                 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]);
8653                         // now add ambient passes if needed
8654                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8655                         {
8656                                 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]);
8657                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8658                                         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]);
8659                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8660                                         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]);
8661                         }
8662                 }
8663                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8664                         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]);
8665                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8666                 {
8667                         // if this is opaque use alpha blend which will darken the earlier
8668                         // passes cheaply.
8669                         //
8670                         // if this is an alpha blended material, all the earlier passes
8671                         // were darkened by fog already, so we only need to add the fog
8672                         // color ontop through the fog mask texture
8673                         //
8674                         // if this is an additive blended material, all the earlier passes
8675                         // were darkened by fog already, and we should not add fog color
8676                         // (because the background was not darkened, there is no fog color
8677                         // that was lost behind it).
8678                         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]);
8679                 }
8680         }
8681
8682         return t->currentframe;
8683 }
8684
8685 rsurfacestate_t rsurface;
8686
8687 void R_Mesh_ResizeArrays(int newvertices)
8688 {
8689         float *base;
8690         if (rsurface.array_size >= newvertices)
8691                 return;
8692         if (rsurface.array_modelvertex3f)
8693                 Mem_Free(rsurface.array_modelvertex3f);
8694         rsurface.array_size = (newvertices + 1023) & ~1023;
8695         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
8696         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
8697         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
8698         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
8699         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
8700         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
8701         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
8702         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
8703         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
8704         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
8705         rsurface.array_color4f           = base + rsurface.array_size * 27;
8706         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
8707 }
8708
8709 void RSurf_ActiveWorldEntity(void)
8710 {
8711         dp_model_t *model = r_refdef.scene.worldmodel;
8712         //if (rsurface.entity == r_refdef.scene.worldentity)
8713         //      return;
8714         rsurface.entity = r_refdef.scene.worldentity;
8715         rsurface.skeleton = NULL;
8716         rsurface.ent_skinnum = 0;
8717         rsurface.ent_qwskin = -1;
8718         rsurface.ent_shadertime = 0;
8719         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8720         if (rsurface.array_size < model->surfmesh.num_vertices)
8721                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
8722         rsurface.matrix = identitymatrix;
8723         rsurface.inversematrix = identitymatrix;
8724         rsurface.matrixscale = 1;
8725         rsurface.inversematrixscale = 1;
8726         R_EntityMatrix(&identitymatrix);
8727         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8728         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8729         rsurface.fograngerecip = r_refdef.fograngerecip;
8730         rsurface.fogheightfade = r_refdef.fogheightfade;
8731         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8732         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8733         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8734         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8735         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8736         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8737         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8738         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8739         rsurface.colormod[3] = 1;
8740         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);
8741         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8742         rsurface.frameblend[0].lerp = 1;
8743         rsurface.ent_alttextures = false;
8744         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8745         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8746         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8747         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
8748         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8749         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8750         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
8751         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8752         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8753         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
8754         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8755         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8756         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
8757         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8758         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8759         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
8760         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8761         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8762         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
8763         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8764         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8765         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
8766         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8767         rsurface.modelelement3i = model->surfmesh.data_element3i;
8768         rsurface.modelelement3s = model->surfmesh.data_element3s;
8769         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
8770         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
8771         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8772         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
8773         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
8774         rsurface.modelsurfaces = model->data_surfaces;
8775         rsurface.generatedvertex = false;
8776         rsurface.vertex3f  = rsurface.modelvertex3f;
8777         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
8778         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8779         rsurface.svector3f = rsurface.modelsvector3f;
8780         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
8781         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8782         rsurface.tvector3f = rsurface.modeltvector3f;
8783         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
8784         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8785         rsurface.normal3f  = rsurface.modelnormal3f;
8786         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
8787         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8788         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
8789 }
8790
8791 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8792 {
8793         dp_model_t *model = ent->model;
8794         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8795         //      return;
8796         rsurface.entity = (entity_render_t *)ent;
8797         rsurface.skeleton = ent->skeleton;
8798         rsurface.ent_skinnum = ent->skinnum;
8799         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;
8800         rsurface.ent_shadertime = ent->shadertime;
8801         rsurface.ent_flags = ent->flags;
8802         if (rsurface.array_size < model->surfmesh.num_vertices)
8803                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
8804         rsurface.matrix = ent->matrix;
8805         rsurface.inversematrix = ent->inversematrix;
8806         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8807         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8808         R_EntityMatrix(&rsurface.matrix);
8809         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8810         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8811         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8812         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8813         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8814         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8815         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8816         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8817         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8818         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8819         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8820         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8821         rsurface.colormod[3] = ent->alpha;
8822         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8823         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8824         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8825         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8826         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8827         if (ent->model->brush.submodel && !prepass)
8828         {
8829                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8830                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8831         }
8832         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
8833         {
8834                 if (ent->animcache_vertex3f && !r_framedata_failed)
8835                 {
8836                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8837                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8838                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8839                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8840                 }
8841                 else if (wanttangents)
8842                 {
8843                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
8844                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
8845                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
8846                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
8847                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
8848                 }
8849                 else if (wantnormals)
8850                 {
8851                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
8852                         rsurface.modelsvector3f = NULL;
8853                         rsurface.modeltvector3f = NULL;
8854                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
8855                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
8856                 }
8857                 else
8858                 {
8859                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
8860                         rsurface.modelsvector3f = NULL;
8861                         rsurface.modeltvector3f = NULL;
8862                         rsurface.modelnormal3f = NULL;
8863                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
8864                 }
8865                 rsurface.modelvertex3f_bufferobject = 0;
8866                 rsurface.modelvertex3f_bufferoffset = 0;
8867                 rsurface.modelsvector3f_bufferobject = 0;
8868                 rsurface.modelsvector3f_bufferoffset = 0;
8869                 rsurface.modeltvector3f_bufferobject = 0;
8870                 rsurface.modeltvector3f_bufferoffset = 0;
8871                 rsurface.modelnormal3f_bufferobject = 0;
8872                 rsurface.modelnormal3f_bufferoffset = 0;
8873                 rsurface.generatedvertex = true;
8874         }
8875         else
8876         {
8877                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8878                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
8879                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8880                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8881                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
8882                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8883                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8884                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
8885                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8886                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8887                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
8888                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8889                 rsurface.generatedvertex = false;
8890         }
8891         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8892         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
8893         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8894         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8895         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
8896         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8897         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8898         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
8899         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8900         rsurface.modelelement3i = model->surfmesh.data_element3i;
8901         rsurface.modelelement3s = model->surfmesh.data_element3s;
8902         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
8903         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
8904         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8905         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
8906         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
8907         rsurface.modelsurfaces = model->data_surfaces;
8908         rsurface.vertex3f  = rsurface.modelvertex3f;
8909         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
8910         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8911         rsurface.svector3f = rsurface.modelsvector3f;
8912         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
8913         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8914         rsurface.tvector3f = rsurface.modeltvector3f;
8915         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
8916         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8917         rsurface.normal3f  = rsurface.modelnormal3f;
8918         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
8919         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8920         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
8921 }
8922
8923 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)
8924 {
8925         rsurface.entity = r_refdef.scene.worldentity;
8926         rsurface.skeleton = NULL;
8927         rsurface.ent_skinnum = 0;
8928         rsurface.ent_qwskin = -1;
8929         rsurface.ent_shadertime = shadertime;
8930         rsurface.ent_flags = entflags;
8931         rsurface.modelnum_vertices = numvertices;
8932         rsurface.modelnum_triangles = numtriangles;
8933         if (rsurface.array_size < rsurface.modelnum_vertices)
8934                 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
8935         rsurface.matrix = *matrix;
8936         rsurface.inversematrix = *inversematrix;
8937         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8938         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8939         R_EntityMatrix(&rsurface.matrix);
8940         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8941         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8942         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8943         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8944         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8945         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8946         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8947         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8948         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8949         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8950         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8951         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8952         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);
8953         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8954         rsurface.frameblend[0].lerp = 1;
8955         rsurface.ent_alttextures = false;
8956         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8957         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8958         if (wanttangents)
8959         {
8960                 rsurface.modelvertex3f = vertex3f;
8961                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
8962                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
8963                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
8964         }
8965         else if (wantnormals)
8966         {
8967                 rsurface.modelvertex3f = vertex3f;
8968                 rsurface.modelsvector3f = NULL;
8969                 rsurface.modeltvector3f = NULL;
8970                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
8971         }
8972         else
8973         {
8974                 rsurface.modelvertex3f = vertex3f;
8975                 rsurface.modelsvector3f = NULL;
8976                 rsurface.modeltvector3f = NULL;
8977                 rsurface.modelnormal3f = NULL;
8978         }
8979         rsurface.modelvertex3f_bufferobject = 0;
8980         rsurface.modelvertex3f_bufferoffset = 0;
8981         rsurface.modelsvector3f_bufferobject = 0;
8982         rsurface.modelsvector3f_bufferoffset = 0;
8983         rsurface.modeltvector3f_bufferobject = 0;
8984         rsurface.modeltvector3f_bufferoffset = 0;
8985         rsurface.modelnormal3f_bufferobject = 0;
8986         rsurface.modelnormal3f_bufferoffset = 0;
8987         rsurface.generatedvertex = true;
8988         rsurface.modellightmapcolor4f  = color4f;
8989         rsurface.modellightmapcolor4f_bufferobject = 0;
8990         rsurface.modellightmapcolor4f_bufferoffset = 0;
8991         rsurface.modeltexcoordtexture2f  = texcoord2f;
8992         rsurface.modeltexcoordtexture2f_bufferobject = 0;
8993         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8994         rsurface.modeltexcoordlightmap2f  = NULL;
8995         rsurface.modeltexcoordlightmap2f_bufferobject = 0;
8996         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8997         rsurface.modelelement3i = element3i;
8998         rsurface.modelelement3s = element3s;
8999         rsurface.modelelement3i_bufferobject = 0;
9000         rsurface.modelelement3s_bufferobject = 0;
9001         rsurface.modellightmapoffsets = NULL;
9002         rsurface.modelsurfaces = NULL;
9003         rsurface.vertex3f  = rsurface.modelvertex3f;
9004         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9005         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9006         rsurface.svector3f = rsurface.modelsvector3f;
9007         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9008         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9009         rsurface.tvector3f = rsurface.modeltvector3f;
9010         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9011         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9012         rsurface.normal3f  = rsurface.modelnormal3f;
9013         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9014         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9015         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9016
9017         if (rsurface.modelnum_vertices && rsurface.modelelement3i)
9018         {
9019                 if ((wantnormals || wanttangents) && !normal3f)
9020                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9021                 if (wanttangents && !svector3f)
9022                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
9023         }
9024 }
9025
9026 float RSurf_FogPoint(const float *v)
9027 {
9028         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9029         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9030         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9031         float FogHeightFade = r_refdef.fogheightfade;
9032         float fogfrac;
9033         unsigned int fogmasktableindex;
9034         if (r_refdef.fogplaneviewabove)
9035                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9036         else
9037                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9038         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9039         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9040 }
9041
9042 float RSurf_FogVertex(const float *v)
9043 {
9044         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9045         float FogPlaneViewDist = rsurface.fogplaneviewdist;
9046         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9047         float FogHeightFade = rsurface.fogheightfade;
9048         float fogfrac;
9049         unsigned int fogmasktableindex;
9050         if (r_refdef.fogplaneviewabove)
9051                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9052         else
9053                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9054         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9055         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9056 }
9057
9058 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9059 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9060 {
9061         int deformindex;
9062         int texturesurfaceindex;
9063         int i, j;
9064         float amplitude;
9065         float animpos;
9066         float scale;
9067         const float *v1, *in_tc;
9068         float *out_tc;
9069         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9070         float waveparms[4];
9071         q3shaderinfo_deform_t *deform;
9072         // if vertices are dynamic (animated models), generate them into the temporary rsurface.array_model* arrays and point rsurface.model* at them instead of the static data from the model itself
9073         if (rsurface.generatedvertex)
9074         {
9075                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
9076                         generatenormals = true;
9077                 for (i = 0;i < Q3MAXDEFORMS;i++)
9078                 {
9079                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
9080                         {
9081                                 generatetangents = true;
9082                                 generatenormals = true;
9083                         }
9084                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
9085                                 generatenormals = true;
9086                 }
9087                 if (generatenormals && !rsurface.modelnormal3f)
9088                 {
9089                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9090                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
9091                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
9092                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9093                 }
9094                 if (generatetangents && !rsurface.modelsvector3f)
9095                 {
9096                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9097                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
9098                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
9099                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9100                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
9101                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
9102                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
9103                 }
9104         }
9105         rsurface.vertex3f  = rsurface.modelvertex3f;
9106         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9107         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9108         rsurface.svector3f = rsurface.modelsvector3f;
9109         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9110         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9111         rsurface.tvector3f = rsurface.modeltvector3f;
9112         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9113         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9114         rsurface.normal3f  = rsurface.modelnormal3f;
9115         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9116         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9117         // if vertices are deformed (sprite flares and things in maps, possibly
9118         // water waves, bulges and other deformations), generate them into
9119         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
9120         // (may be static model data or generated data for an animated model, or
9121         //  the previous deform pass)
9122         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
9123         {
9124                 switch (deform->deform)
9125                 {
9126                 default:
9127                 case Q3DEFORM_PROJECTIONSHADOW:
9128                 case Q3DEFORM_TEXT0:
9129                 case Q3DEFORM_TEXT1:
9130                 case Q3DEFORM_TEXT2:
9131                 case Q3DEFORM_TEXT3:
9132                 case Q3DEFORM_TEXT4:
9133                 case Q3DEFORM_TEXT5:
9134                 case Q3DEFORM_TEXT6:
9135                 case Q3DEFORM_TEXT7:
9136                 case Q3DEFORM_NONE:
9137                         break;
9138                 case Q3DEFORM_AUTOSPRITE:
9139                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9140                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9141                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9142                         VectorNormalize(newforward);
9143                         VectorNormalize(newright);
9144                         VectorNormalize(newup);
9145                         // make deformed versions of only the model vertices used by the specified surfaces
9146                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9147                         {
9148                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9149                                 // a single autosprite surface can contain multiple sprites...
9150                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9151                                 {
9152                                         VectorClear(center);
9153                                         for (i = 0;i < 4;i++)
9154                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9155                                         VectorScale(center, 0.25f, center);
9156                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
9157                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
9158                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
9159                                         for (i = 0;i < 4;i++)
9160                                         {
9161                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
9162                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9163                                         }
9164                                 }
9165                                 Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformednormal3f, r_smoothnormals_areaweighting.integer != 0);
9166                                 Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modeltexcoordtexture2f, rsurface.array_deformednormal3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformedsvector3f, rsurface.array_deformedtvector3f, r_smoothnormals_areaweighting.integer != 0);
9167                         }
9168                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9169                         rsurface.vertex3f_bufferobject = 0;
9170                         rsurface.vertex3f_bufferoffset = 0;
9171                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9172                         rsurface.svector3f_bufferobject = 0;
9173                         rsurface.svector3f_bufferoffset = 0;
9174                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9175                         rsurface.tvector3f_bufferobject = 0;
9176                         rsurface.tvector3f_bufferoffset = 0;
9177                         rsurface.normal3f = rsurface.array_deformednormal3f;
9178                         rsurface.normal3f_bufferobject = 0;
9179                         rsurface.normal3f_bufferoffset = 0;
9180                         break;
9181                 case Q3DEFORM_AUTOSPRITE2:
9182                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9183                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9184                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9185                         VectorNormalize(newforward);
9186                         VectorNormalize(newright);
9187                         VectorNormalize(newup);
9188                         // make deformed versions of only the model vertices used by the specified surfaces
9189                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9190                         {
9191                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9192                                 const float *v1, *v2;
9193                                 vec3_t start, end;
9194                                 float f, l;
9195                                 struct
9196                                 {
9197                                         float length2;
9198                                         const float *v1;
9199                                         const float *v2;
9200                                 }
9201                                 shortest[2];
9202                                 memset(shortest, 0, sizeof(shortest));
9203                                 // a single autosprite surface can contain multiple sprites...
9204                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9205                                 {
9206                                         VectorClear(center);
9207                                         for (i = 0;i < 4;i++)
9208                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9209                                         VectorScale(center, 0.25f, center);
9210                                         // find the two shortest edges, then use them to define the
9211                                         // axis vectors for rotating around the central axis
9212                                         for (i = 0;i < 6;i++)
9213                                         {
9214                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
9215                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
9216 #if 0
9217                                                 Debug_PolygonBegin(NULL, 0);
9218                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
9219                                                 Debug_PolygonVertex((v1[0] + v2[0]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 4, (v1[1] + v2[1]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1], (v1[2] + v2[2]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2], 0, 0, 1, 1, 0, 1);
9220                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
9221                                                 Debug_PolygonEnd();
9222 #endif
9223                                                 l = VectorDistance2(v1, v2);
9224                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9225                                                 if (v1[2] != v2[2])
9226                                                         l += (1.0f / 1024.0f);
9227                                                 if (shortest[0].length2 > l || i == 0)
9228                                                 {
9229                                                         shortest[1] = shortest[0];
9230                                                         shortest[0].length2 = l;
9231                                                         shortest[0].v1 = v1;
9232                                                         shortest[0].v2 = v2;
9233                                                 }
9234                                                 else if (shortest[1].length2 > l || i == 1)
9235                                                 {
9236                                                         shortest[1].length2 = l;
9237                                                         shortest[1].v1 = v1;
9238                                                         shortest[1].v2 = v2;
9239                                                 }
9240                                         }
9241                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9242                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9243 #if 0
9244                                         Debug_PolygonBegin(NULL, 0);
9245                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
9246                                         Debug_PolygonVertex(center[0] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 4, center[1] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1] * 4, center[2] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2] * 4, 0, 0, 0, 1, 0, 1);
9247                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
9248                                         Debug_PolygonEnd();
9249 #endif
9250                                         // this calculates the right vector from the shortest edge
9251                                         // and the up vector from the edge midpoints
9252                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9253                                         VectorNormalize(right);
9254                                         VectorSubtract(end, start, up);
9255                                         VectorNormalize(up);
9256                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9257                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9258                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9259                                         VectorNegate(forward, forward);
9260                                         VectorReflect(forward, 0, up, forward);
9261                                         VectorNormalize(forward);
9262                                         CrossProduct(up, forward, newright);
9263                                         VectorNormalize(newright);
9264 #if 0
9265                                         Debug_PolygonBegin(NULL, 0);
9266                                         Debug_PolygonVertex(center[0] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 8, center[1] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1] * 8, center[2] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2] * 8, 0, 0, 1, 0, 0, 1);
9267                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
9268                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
9269                                         Debug_PolygonEnd();
9270 #endif
9271 #if 0
9272                                         Debug_PolygonBegin(NULL, 0);
9273                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
9274                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
9275                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
9276                                         Debug_PolygonEnd();
9277 #endif
9278                                         // rotate the quad around the up axis vector, this is made
9279                                         // especially easy by the fact we know the quad is flat,
9280                                         // so we only have to subtract the center position and
9281                                         // measure distance along the right vector, and then
9282                                         // multiply that by the newright vector and add back the
9283                                         // center position
9284                                         // we also need to subtract the old position to undo the
9285                                         // displacement from the center, which we do with a
9286                                         // DotProduct, the subtraction/addition of center is also
9287                                         // optimized into DotProducts here
9288                                         l = DotProduct(right, center);
9289                                         for (i = 0;i < 4;i++)
9290                                         {
9291                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
9292                                                 f = DotProduct(right, v1) - l;
9293                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9294                                         }
9295                                 }
9296                                 Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformednormal3f, r_smoothnormals_areaweighting.integer != 0);
9297                                 Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modeltexcoordtexture2f, rsurface.array_deformednormal3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformedsvector3f, rsurface.array_deformedtvector3f, r_smoothnormals_areaweighting.integer != 0);
9298                         }
9299                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9300                         rsurface.vertex3f_bufferobject = 0;
9301                         rsurface.vertex3f_bufferoffset = 0;
9302                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9303                         rsurface.svector3f_bufferobject = 0;
9304                         rsurface.svector3f_bufferoffset = 0;
9305                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9306                         rsurface.tvector3f_bufferobject = 0;
9307                         rsurface.tvector3f_bufferoffset = 0;
9308                         rsurface.normal3f = rsurface.array_deformednormal3f;
9309                         rsurface.normal3f_bufferobject = 0;
9310                         rsurface.normal3f_bufferoffset = 0;
9311                         break;
9312                 case Q3DEFORM_NORMAL:
9313                         // deform the normals to make reflections wavey
9314                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9315                         {
9316                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9317                                 for (j = 0;j < surface->num_vertices;j++)
9318                                 {
9319                                         float vertex[3];
9320                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
9321                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
9322                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
9323                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9324                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9325                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9326                                         VectorNormalize(normal);
9327                                 }
9328                                 Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modeltexcoordtexture2f, rsurface.array_deformednormal3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformedsvector3f, rsurface.array_deformedtvector3f, r_smoothnormals_areaweighting.integer != 0);
9329                         }
9330                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9331                         rsurface.svector3f_bufferobject = 0;
9332                         rsurface.svector3f_bufferoffset = 0;
9333                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9334                         rsurface.tvector3f_bufferobject = 0;
9335                         rsurface.tvector3f_bufferoffset = 0;
9336                         rsurface.normal3f = rsurface.array_deformednormal3f;
9337                         rsurface.normal3f_bufferobject = 0;
9338                         rsurface.normal3f_bufferoffset = 0;
9339                         break;
9340                 case Q3DEFORM_WAVE:
9341                         // deform vertex array to make wavey water and flags and such
9342                         waveparms[0] = deform->waveparms[0];
9343                         waveparms[1] = deform->waveparms[1];
9344                         waveparms[2] = deform->waveparms[2];
9345                         waveparms[3] = deform->waveparms[3];
9346                         // this is how a divisor of vertex influence on deformation
9347                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9348                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9349                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9350                         {
9351                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9352                                 for (j = 0;j < surface->num_vertices;j++)
9353                                 {
9354                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
9355                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9356                                         // if the wavefunc depends on time, evaluate it per-vertex
9357                                         if (waveparms[3])
9358                                         {
9359                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
9360                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9361                                         }
9362                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9363                                 }
9364                         }
9365                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9366                         rsurface.vertex3f_bufferobject = 0;
9367                         rsurface.vertex3f_bufferoffset = 0;
9368                         break;
9369                 case Q3DEFORM_BULGE:
9370                         // deform vertex array to make the surface have moving bulges
9371                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9372                         {
9373                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9374                                 for (j = 0;j < surface->num_vertices;j++)
9375                                 {
9376                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
9377                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9378                                 }
9379                         }
9380                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9381                         rsurface.vertex3f_bufferobject = 0;
9382                         rsurface.vertex3f_bufferoffset = 0;
9383                         break;
9384                 case Q3DEFORM_MOVE:
9385                         // deform vertex array
9386                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9387                         VectorScale(deform->parms, scale, waveparms);
9388                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9389                         {
9390                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9391                                 for (j = 0;j < surface->num_vertices;j++)
9392                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9393                         }
9394                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9395                         rsurface.vertex3f_bufferobject = 0;
9396                         rsurface.vertex3f_bufferoffset = 0;
9397                         break;
9398                 }
9399         }
9400         // generate texcoords based on the chosen texcoord source
9401         switch(rsurface.texture->tcgen.tcgen)
9402         {
9403         default:
9404         case Q3TCGEN_TEXTURE:
9405                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
9406                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
9407                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9408                 break;
9409         case Q3TCGEN_LIGHTMAP:
9410                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
9411                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
9412                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
9413                 break;
9414         case Q3TCGEN_VECTOR:
9415                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9416                 {
9417                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9418                         for (j = 0, v1 = rsurface.modelvertex3f + 3 * surface->num_firstvertex, out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;j < surface->num_vertices;j++, v1 += 3, out_tc += 2)
9419                         {
9420                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
9421                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
9422                         }
9423                 }
9424                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9425                 rsurface.texcoordtexture2f_bufferobject  = 0;
9426                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9427                 break;
9428         case Q3TCGEN_ENVIRONMENT:
9429                 // make environment reflections using a spheremap
9430                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9431                 {
9432                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9433                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
9434                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
9435                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
9436                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
9437                         {
9438                                 // identical to Q3A's method, but executed in worldspace so
9439                                 // carried models can be shiny too
9440
9441                                 float viewer[3], d, reflected[3], worldreflected[3];
9442
9443                                 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
9444                                 // VectorNormalize(viewer);
9445
9446                                 d = DotProduct(normal, viewer);
9447
9448                                 reflected[0] = normal[0]*2*d - viewer[0];
9449                                 reflected[1] = normal[1]*2*d - viewer[1];
9450                                 reflected[2] = normal[2]*2*d - viewer[2];
9451                                 // note: this is proportinal to viewer, so we can normalize later
9452
9453                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9454                                 VectorNormalize(worldreflected);
9455
9456                                 // note: this sphere map only uses world x and z!
9457                                 // so positive and negative y will LOOK THE SAME.
9458                                 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
9459                                 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
9460                         }
9461                 }
9462                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9463                 rsurface.texcoordtexture2f_bufferobject  = 0;
9464                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9465                 break;
9466         }
9467         // the only tcmod that needs software vertex processing is turbulent, so
9468         // check for it here and apply the changes if needed
9469         // and we only support that as the first one
9470         // (handling a mixture of turbulent and other tcmods would be problematic
9471         //  without punting it entirely to a software path)
9472         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9473         {
9474                 amplitude = rsurface.texture->tcmods[0].parms[1];
9475                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
9476                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9477                 {
9478                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9479                         for (j = 0, v1 = rsurface.modelvertex3f + 3 * surface->num_firstvertex, in_tc = rsurface.texcoordtexture2f + 2 * surface->num_firstvertex, out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;j < surface->num_vertices;j++, v1 += 3, in_tc += 2, out_tc += 2)
9480                         {
9481                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9482                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9483                         }
9484                 }
9485                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9486                 rsurface.texcoordtexture2f_bufferobject  = 0;
9487                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9488         }
9489         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
9490         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
9491         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9492         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
9493 }
9494
9495 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9496 {
9497         int i, j;
9498         const msurface_t *surface = texturesurfacelist[0];
9499         const msurface_t *surface2;
9500         int firstvertex;
9501         int endvertex;
9502         int numvertices;
9503         int numtriangles;
9504         // TODO: lock all array ranges before render, rather than on each surface
9505         if (texturenumsurfaces == 1)
9506         {
9507                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9508                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9509         }
9510         else if (r_batchmode.integer == 2)
9511         {
9512                 #define MAXBATCHTRIANGLES 4096
9513                 int batchtriangles = 0;
9514                 static int batchelements[MAXBATCHTRIANGLES*3];
9515                 for (i = 0;i < texturenumsurfaces;i = j)
9516                 {
9517                         surface = texturesurfacelist[i];
9518                         j = i + 1;
9519                         if (surface->num_triangles > MAXBATCHTRIANGLES)
9520                         {
9521                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9522                                 continue;
9523                         }
9524                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9525                         batchtriangles = surface->num_triangles;
9526                         firstvertex = surface->num_firstvertex;
9527                         endvertex = surface->num_firstvertex + surface->num_vertices;
9528                         for (;j < texturenumsurfaces;j++)
9529                         {
9530                                 surface2 = texturesurfacelist[j];
9531                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9532                                         break;
9533                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9534                                 batchtriangles += surface2->num_triangles;
9535                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
9536                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9537                         }
9538                         surface2 = texturesurfacelist[j-1];
9539                         numvertices = endvertex - firstvertex;
9540                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9541                 }
9542         }
9543         else if (r_batchmode.integer == 1)
9544         {
9545                 for (i = 0;i < texturenumsurfaces;i = j)
9546                 {
9547                         surface = texturesurfacelist[i];
9548                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9549                                 if (texturesurfacelist[j] != surface2)
9550                                         break;
9551                         surface2 = texturesurfacelist[j-1];
9552                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9553                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9554                         GL_LockArrays(surface->num_firstvertex, numvertices);
9555                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9556                 }
9557         }
9558         else
9559         {
9560                 for (i = 0;i < texturenumsurfaces;i++)
9561                 {
9562                         surface = texturesurfacelist[i];
9563                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9564                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9565                 }
9566         }
9567 }
9568
9569 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
9570 {
9571         switch(vid.renderpath)
9572         {
9573         case RENDERPATH_CGGL:
9574 #ifdef SUPPORTCG
9575                 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
9576                 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
9577 #endif
9578                 break;
9579         case RENDERPATH_GL20:
9580                 if (r_glsl_permutation->loc_Texture_Lightmap  >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
9581                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
9582                 break;
9583         case RENDERPATH_GL13:
9584         case RENDERPATH_GL11:
9585                 R_Mesh_TexBind(0, surface->lightmaptexture);
9586                 break;
9587         }
9588 }
9589
9590 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
9591 {
9592         // pick the closest matching water plane and bind textures
9593         int planeindex, vertexindex;
9594         float d, bestd;
9595         vec3_t vert;
9596         const float *v;
9597         r_waterstate_waterplane_t *p, *bestp;
9598         bestd = 0;
9599         bestp = NULL;
9600         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9601         {
9602                 d = 0;
9603                 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
9604                 {
9605                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9606                         d += fabs(PlaneDiff(vert, &p->plane));
9607                 }
9608                 if (bestd > d || !bestp)
9609                 {
9610                         bestd = d;
9611                         bestp = p;
9612                 }
9613         }
9614         switch(vid.renderpath)
9615         {
9616         case RENDERPATH_CGGL:
9617 #ifdef SUPPORTCG
9618                 if (r_cg_permutation->fp_Texture_Refraction) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR
9619                 if (r_cg_permutation->fp_Texture_Reflection) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR
9620 #endif
9621                 break;
9622         case RENDERPATH_GL20:
9623                 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
9624                 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
9625                 break;
9626         case RENDERPATH_GL13:
9627         case RENDERPATH_GL11:
9628                 break;
9629         }
9630 }
9631
9632 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9633 {
9634         int i;
9635         const msurface_t *surface;
9636         if (r_waterstate.renderingscene)
9637                 return;
9638         for (i = 0;i < texturenumsurfaces;i++)
9639         {
9640                 surface = texturesurfacelist[i];
9641                 RSurf_BindLightmapForSurface(surface);
9642                 RSurf_BindReflectionForSurface(surface);
9643                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9644                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9645         }
9646 }
9647
9648 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9649 {
9650         int i;
9651         int j;
9652         const msurface_t *surface = texturesurfacelist[0];
9653         const msurface_t *surface2;
9654         int firstvertex;
9655         int endvertex;
9656         int numvertices;
9657         int numtriangles;
9658         if (texturenumsurfaces == 1)
9659         {
9660                 RSurf_BindLightmapForSurface(surface);
9661                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9662                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9663         }
9664         else if (r_batchmode.integer == 2)
9665         {
9666 #define MAXBATCHTRIANGLES 4096
9667                 int batchtriangles = 0;
9668                 static int batchelements[MAXBATCHTRIANGLES*3];
9669                 for (i = 0;i < texturenumsurfaces;i = j)
9670                 {
9671                         surface = texturesurfacelist[i];
9672                         RSurf_BindLightmapForSurface(surface);
9673                         j = i + 1;
9674                         if (surface->num_triangles > MAXBATCHTRIANGLES)
9675                         {
9676                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9677                                 continue;
9678                         }
9679                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9680                         batchtriangles = surface->num_triangles;
9681                         firstvertex = surface->num_firstvertex;
9682                         endvertex = surface->num_firstvertex + surface->num_vertices;
9683                         for (;j < texturenumsurfaces;j++)
9684                         {
9685                                 surface2 = texturesurfacelist[j];
9686                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9687                                         break;
9688                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9689                                 batchtriangles += surface2->num_triangles;
9690                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
9691                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9692                         }
9693                         surface2 = texturesurfacelist[j-1];
9694                         numvertices = endvertex - firstvertex;
9695                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9696                 }
9697         }
9698         else if (r_batchmode.integer == 1)
9699         {
9700 #if 0
9701                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
9702                 for (i = 0;i < texturenumsurfaces;i = j)
9703                 {
9704                         surface = texturesurfacelist[i];
9705                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9706                                 if (texturesurfacelist[j] != surface2)
9707                                         break;
9708                         Con_Printf(" %i", j - i);
9709                 }
9710                 Con_Printf("\n");
9711                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
9712 #endif
9713                 for (i = 0;i < texturenumsurfaces;i = j)
9714                 {
9715                         surface = texturesurfacelist[i];
9716                         RSurf_BindLightmapForSurface(surface);
9717                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9718                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
9719                                         break;
9720 #if 0
9721                         Con_Printf(" %i", j - i);
9722 #endif
9723                         surface2 = texturesurfacelist[j-1];
9724                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9725                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9726                         GL_LockArrays(surface->num_firstvertex, numvertices);
9727                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9728                 }
9729 #if 0
9730                 Con_Printf("\n");
9731 #endif
9732         }
9733         else
9734         {
9735                 for (i = 0;i < texturenumsurfaces;i++)
9736                 {
9737                         surface = texturesurfacelist[i];
9738                         RSurf_BindLightmapForSurface(surface);
9739                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9740                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9741                 }
9742         }
9743 }
9744
9745 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9746 {
9747         int j;
9748         int texturesurfaceindex;
9749         if (r_showsurfaces.integer == 2)
9750         {
9751                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9752                 {
9753                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9754                         for (j = 0;j < surface->num_triangles;j++)
9755                         {
9756                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
9757                                 GL_Color(f, f, f, 1);
9758                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9759                         }
9760                 }
9761         }
9762         else
9763         {
9764                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9765                 {
9766                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9767                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
9768                         GL_Color((k & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, ((k >> 4) & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, ((k >> 8) & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, 1);
9769                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9770                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9771                 }
9772         }
9773 }
9774
9775 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9776 {
9777         int texturesurfaceindex;
9778         int i;
9779         const float *v;
9780         float *c2;
9781         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9782         {
9783                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9784                 for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c2 += 4)
9785                 {
9786                         c2[0] = 0.5;
9787                         c2[1] = 0.5;
9788                         c2[2] = 0.5;
9789                         c2[3] = 1;
9790                 }
9791         }
9792         rsurface.lightmapcolor4f = rsurface.array_color4f;
9793         rsurface.lightmapcolor4f_bufferobject = 0;
9794         rsurface.lightmapcolor4f_bufferoffset = 0;
9795 }
9796
9797 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9798 {
9799         int texturesurfaceindex;
9800         int i;
9801         float f;
9802         const float *v;
9803         const float *c;
9804         float *c2;
9805         if (rsurface.lightmapcolor4f)
9806         {
9807                 // generate color arrays for the surfaces in this list
9808                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9809                 {
9810                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9811                         for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c = (rsurface.lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4, c2 += 4)
9812                         {
9813                                 f = RSurf_FogVertex(v);
9814                                 c2[0] = c[0] * f;
9815                                 c2[1] = c[1] * f;
9816                                 c2[2] = c[2] * f;
9817                                 c2[3] = c[3];
9818                         }
9819                 }
9820         }
9821         else
9822         {
9823                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9824                 {
9825                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9826                         for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c2 += 4)
9827                         {
9828                                 f = RSurf_FogVertex(v);
9829                                 c2[0] = f;
9830                                 c2[1] = f;
9831                                 c2[2] = f;
9832                                 c2[3] = 1;
9833                         }
9834                 }
9835         }
9836         rsurface.lightmapcolor4f = rsurface.array_color4f;
9837         rsurface.lightmapcolor4f_bufferobject = 0;
9838         rsurface.lightmapcolor4f_bufferoffset = 0;
9839 }
9840
9841 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9842 {
9843         int texturesurfaceindex;
9844         int i;
9845         float f;
9846         const float *v;
9847         const float *c;
9848         float *c2;
9849         if (!rsurface.lightmapcolor4f)
9850                 return;
9851         // generate color arrays for the surfaces in this list
9852         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9853         {
9854                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9855                 for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c = (rsurface.lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4, c2 += 4)
9856                 {
9857                         f = RSurf_FogVertex(v);
9858                         c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9859                         c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9860                         c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9861                         c2[3] = c[3];
9862                 }
9863         }
9864         rsurface.lightmapcolor4f = rsurface.array_color4f;
9865         rsurface.lightmapcolor4f_bufferobject = 0;
9866         rsurface.lightmapcolor4f_bufferoffset = 0;
9867 }
9868
9869 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
9870 {
9871         int texturesurfaceindex;
9872         int i;
9873         const float *c;
9874         float *c2;
9875         if (!rsurface.lightmapcolor4f)
9876                 return;
9877         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9878         {
9879                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9880                 for (i = 0, c = (rsurface.lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4, c2 += 4)
9881                 {
9882                         c2[0] = c[0] * r;
9883                         c2[1] = c[1] * g;
9884                         c2[2] = c[2] * b;
9885                         c2[3] = c[3] * a;
9886                 }
9887         }
9888         rsurface.lightmapcolor4f = rsurface.array_color4f;
9889         rsurface.lightmapcolor4f_bufferobject = 0;
9890         rsurface.lightmapcolor4f_bufferoffset = 0;
9891 }
9892
9893 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9894 {
9895         int texturesurfaceindex;
9896         int i;
9897         const float *c;
9898         float *c2;
9899         if (!rsurface.lightmapcolor4f)
9900                 return;
9901         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9902         {
9903                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9904                 for (i = 0, c = (rsurface.lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4, c2 += 4)
9905                 {
9906                         c2[0] = c[0] + r_refdef.scene.ambient;
9907                         c2[1] = c[1] + r_refdef.scene.ambient;
9908                         c2[2] = c[2] + r_refdef.scene.ambient;
9909                         c2[3] = c[3];
9910                 }
9911         }
9912         rsurface.lightmapcolor4f = rsurface.array_color4f;
9913         rsurface.lightmapcolor4f_bufferobject = 0;
9914         rsurface.lightmapcolor4f_bufferoffset = 0;
9915 }
9916
9917 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9918 {
9919         // TODO: optimize
9920         rsurface.lightmapcolor4f = NULL;
9921         rsurface.lightmapcolor4f_bufferobject = 0;
9922         rsurface.lightmapcolor4f_bufferoffset = 0;
9923         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
9924         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
9925         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
9926         GL_Color(r, g, b, a);
9927         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
9928 }
9929
9930 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9931 {
9932         // TODO: optimize applyfog && applycolor case
9933         // just apply fog if necessary, and tint the fog color array if necessary
9934         rsurface.lightmapcolor4f = NULL;
9935         rsurface.lightmapcolor4f_bufferobject = 0;
9936         rsurface.lightmapcolor4f_bufferoffset = 0;
9937         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
9938         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
9939         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
9940         GL_Color(r, g, b, a);
9941         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9942 }
9943
9944 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9945 {
9946         int texturesurfaceindex;
9947         int i;
9948         float *c;
9949         // TODO: optimize
9950         if (texturesurfacelist[0]->lightmapinfo)
9951         {
9952                 // generate color arrays for the surfaces in this list
9953                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9954                 {
9955                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9956                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
9957                         {
9958                                 if (surface->lightmapinfo->samples)
9959                                 {
9960                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
9961                                         float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
9962                                         VectorScale(lm, scale, c);
9963                                         if (surface->lightmapinfo->styles[1] != 255)
9964                                         {
9965                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9966                                                 lm += size3;
9967                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
9968                                                 VectorMA(c, scale, lm, c);
9969                                                 if (surface->lightmapinfo->styles[2] != 255)
9970                                                 {
9971                                                         lm += size3;
9972                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
9973                                                         VectorMA(c, scale, lm, c);
9974                                                         if (surface->lightmapinfo->styles[3] != 255)
9975                                                         {
9976                                                                 lm += size3;
9977                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
9978                                                                 VectorMA(c, scale, lm, c);
9979                                                         }
9980                                                 }
9981                                         }
9982                                 }
9983                                 else
9984                                         VectorClear(c);
9985                                 c[3] = 1;
9986                         }
9987                 }
9988                 rsurface.lightmapcolor4f = rsurface.array_color4f;
9989                 rsurface.lightmapcolor4f_bufferobject = 0;
9990                 rsurface.lightmapcolor4f_bufferoffset = 0;
9991         }
9992         else
9993         {
9994                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
9995                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
9996                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
9997         }
9998         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
9999         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10000         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10001         GL_Color(r, g, b, a);
10002         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10003 }
10004
10005 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
10006 {
10007         int texturesurfaceindex;
10008         int i;
10009         float f;
10010         float alpha;
10011         const float *v;
10012         const float *n;
10013         float *c;
10014         vec3_t ambientcolor;
10015         vec3_t diffusecolor;
10016         vec3_t lightdir;
10017         // TODO: optimize
10018         // model lighting
10019         VectorCopy(rsurface.modellight_lightdir, lightdir);
10020         f = 0.5f * r_refdef.lightmapintensity;
10021         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10022         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10023         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10024         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10025         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10026         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10027         alpha = *a;
10028         if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
10029         {
10030                 // generate color arrays for the surfaces in this list
10031                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10032                 {
10033                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10034                         int numverts = surface->num_vertices;
10035                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
10036                         n = rsurface.normal3f + 3 * surface->num_firstvertex;
10037                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
10038                         // q3-style directional shading
10039                         for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
10040                         {
10041                                 if ((f = DotProduct(n, lightdir)) > 0)
10042                                         VectorMA(ambientcolor, f, diffusecolor, c);
10043                                 else
10044                                         VectorCopy(ambientcolor, c);
10045                                 c[3] = alpha;
10046                         }
10047                 }
10048                 *r = 1;
10049                 *g = 1;
10050                 *b = 1;
10051                 *a = 1;
10052                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10053                 rsurface.lightmapcolor4f_bufferobject = 0;
10054                 rsurface.lightmapcolor4f_bufferoffset = 0;
10055                 *applycolor = false;
10056         }
10057         else
10058         {
10059                 *r = ambientcolor[0];
10060                 *g = ambientcolor[1];
10061                 *b = ambientcolor[2];
10062                 rsurface.lightmapcolor4f = NULL;
10063                 rsurface.lightmapcolor4f_bufferobject = 0;
10064                 rsurface.lightmapcolor4f_bufferoffset = 0;
10065         }
10066 }
10067
10068 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10069 {
10070         RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
10071         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10072         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10073         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10074         GL_Color(r, g, b, a);
10075         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10076 }
10077
10078 void RSurf_SetupDepthAndCulling(void)
10079 {
10080         // submodels are biased to avoid z-fighting with world surfaces that they
10081         // may be exactly overlapping (avoids z-fighting artifacts on certain
10082         // doors and things in Quake maps)
10083         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10084         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10085         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10086         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10087 }
10088
10089 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10090 {
10091         // transparent sky would be ridiculous
10092         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10093                 return;
10094         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10095         skyrenderlater = true;
10096         RSurf_SetupDepthAndCulling();
10097         GL_DepthMask(true);
10098         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10099         // skymasking on them, and Quake3 never did sky masking (unlike
10100         // software Quake and software Quake2), so disable the sky masking
10101         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10102         // and skymasking also looks very bad when noclipping outside the
10103         // level, so don't use it then either.
10104         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
10105         {
10106                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10107                 R_Mesh_ColorPointer(NULL, 0, 0);
10108                 R_Mesh_ResetTextureState();
10109                 if (skyrendermasked)
10110                 {
10111                         R_SetupShader_DepthOrShadow();
10112                         // depth-only (masking)
10113                         GL_ColorMask(0,0,0,0);
10114                         // just to make sure that braindead drivers don't draw
10115                         // anything despite that colormask...
10116                         GL_BlendFunc(GL_ZERO, GL_ONE);
10117                 }
10118                 else
10119                 {
10120                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10121                         // fog sky
10122                         GL_BlendFunc(GL_ONE, GL_ZERO);
10123                 }
10124                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10125                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10126                 if (skyrendermasked)
10127                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10128         }
10129         R_Mesh_ResetTextureState();
10130         GL_Color(1, 1, 1, 1);
10131 }
10132
10133 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10134 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10135 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10136 {
10137         qboolean reflect = (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)) && !prepass;
10138         qboolean refract = (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !prepass;
10139
10140         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
10141                 return;
10142
10143         if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
10144                 R_Mesh_ColorPointer(NULL, 0, 0);
10145         else
10146                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
10147
10148         if (refract)
10149         {
10150                 // render background
10151                 GL_BlendFunc(GL_ONE, GL_ZERO);
10152                 GL_DepthMask(true);
10153                 GL_AlphaTest(false);
10154
10155                 GL_Color(1, 1, 1, 1);
10156                 R_Mesh_ColorPointer(NULL, 0, 0);
10157
10158                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
10159                 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10160                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10161                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
10162                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
10163                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
10164                 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10165                 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10166                 GL_LockArrays(0, 0);
10167
10168                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
10169                 GL_DepthMask(false);
10170                 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
10171                         R_Mesh_ColorPointer(NULL, 0, 0);
10172                 else
10173                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
10174         }
10175
10176         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
10177
10178         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10179         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10180         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
10181         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
10182         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
10183         if (!prepass)
10184                 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10185
10186         if (refract)
10187                 GL_DepthMask(true);
10188         else
10189                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10190         GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
10191         GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0 && !r_shadow_usingdeferredprepass);
10192
10193         if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10194         {
10195                 if (refract || reflect)
10196                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10197                 else
10198                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10199         }
10200         else
10201         {
10202                 if (refract || reflect)
10203                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10204                 else
10205                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10206         }
10207         GL_LockArrays(0, 0);
10208 }
10209
10210 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10211 {
10212         // OpenGL 1.3 path - anything not completely ancient
10213         int texturesurfaceindex;
10214         qboolean applycolor;
10215         qboolean applyfog;
10216         int layerindex;
10217         const texturelayer_t *layer;
10218         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10219
10220         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10221         {
10222                 vec4_t layercolor;
10223                 int layertexrgbscale;
10224                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10225                 {
10226                         if (layerindex == 0)
10227                                 GL_AlphaTest(true);
10228                         else
10229                         {
10230                                 GL_AlphaTest(false);
10231                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10232                         }
10233                 }
10234                 GL_DepthMask(layer->depthmask && writedepth);
10235                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10236                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10237                 {
10238                         layertexrgbscale = 4;
10239                         VectorScale(layer->color, 0.25f, layercolor);
10240                 }
10241                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10242                 {
10243                         layertexrgbscale = 2;
10244                         VectorScale(layer->color, 0.5f, layercolor);
10245                 }
10246                 else
10247                 {
10248                         layertexrgbscale = 1;
10249                         VectorScale(layer->color, 1.0f, layercolor);
10250                 }
10251                 layercolor[3] = layer->color[3];
10252                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10253                 R_Mesh_ColorPointer(NULL, 0, 0);
10254                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10255                 switch (layer->type)
10256                 {
10257                 case TEXTURELAYERTYPE_LITTEXTURE:
10258                         // single-pass lightmapped texture with 2x rgbscale
10259                         //R_Mesh_TexBind(0, r_texture_white);
10260                         R_Mesh_TexMatrix(0, NULL);
10261                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10262                         R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10263                         R_Mesh_TexBind(1, layer->texture);
10264                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10265                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10266                         R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10267                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10268                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10269                         else if (rsurface.uselightmaptexture)
10270                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10271                         else
10272                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10273                         break;
10274                 case TEXTURELAYERTYPE_TEXTURE:
10275                         // singletexture unlit texture with transparency support
10276                         R_Mesh_TexBind(0, layer->texture);
10277                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10278                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10279                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10280                         R_Mesh_TexBind(1, 0);
10281                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10282                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10283                         break;
10284                 case TEXTURELAYERTYPE_FOG:
10285                         // singletexture fogging
10286                         if (layer->texture)
10287                         {
10288                                 R_Mesh_TexBind(0, layer->texture);
10289                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10290                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10291                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10292                         }
10293                         else
10294                         {
10295                                 R_Mesh_TexBind(0, 0);
10296                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10297                         }
10298                         R_Mesh_TexBind(1, 0);
10299                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10300                         // generate a color array for the fog pass
10301                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10302                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10303                         {
10304                                 int i;
10305                                 float f;
10306                                 const float *v;
10307                                 float *c;
10308                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10309                                 for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
10310                                 {
10311                                         f = 1 - RSurf_FogVertex(v);
10312                                         c[0] = layercolor[0];
10313                                         c[1] = layercolor[1];
10314                                         c[2] = layercolor[2];
10315                                         c[3] = f * layercolor[3];
10316                                 }
10317                         }
10318                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10319                         break;
10320                 default:
10321                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10322                 }
10323                 GL_LockArrays(0, 0);
10324         }
10325         CHECKGLERROR
10326         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10327         {
10328                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10329                 GL_AlphaTest(false);
10330         }
10331 }
10332
10333 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10334 {
10335         // OpenGL 1.1 - crusty old voodoo path
10336         int texturesurfaceindex;
10337         qboolean applyfog;
10338         int layerindex;
10339         const texturelayer_t *layer;
10340         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10341
10342         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10343         {
10344                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10345                 {
10346                         if (layerindex == 0)
10347                                 GL_AlphaTest(true);
10348                         else
10349                         {
10350                                 GL_AlphaTest(false);
10351                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10352                         }
10353                 }
10354                 GL_DepthMask(layer->depthmask && writedepth);
10355                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10356                 R_Mesh_ColorPointer(NULL, 0, 0);
10357                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10358                 switch (layer->type)
10359                 {
10360                 case TEXTURELAYERTYPE_LITTEXTURE:
10361                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10362                         {
10363                                 // two-pass lit texture with 2x rgbscale
10364                                 // first the lightmap pass
10365                                 //R_Mesh_TexBind(0, r_texture_white);
10366                                 R_Mesh_TexMatrix(0, NULL);
10367                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10368                                 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10369                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10370                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10371                                 else if (rsurface.uselightmaptexture)
10372                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10373                                 else
10374                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10375                                 GL_LockArrays(0, 0);
10376                                 // then apply the texture to it
10377                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10378                                 R_Mesh_TexBind(0, layer->texture);
10379                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10380                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10381                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10382                                 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layer->color[0] * 0.5f, layer->color[1] * 0.5f, layer->color[2] * 0.5f, layer->color[3], layer->color[0] != 2 || layer->color[1] != 2 || layer->color[2] != 2 || layer->color[3] != 1, false);
10383                         }
10384                         else
10385                         {
10386                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10387                                 R_Mesh_TexBind(0, layer->texture);
10388                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10389                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10390                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10391                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10392                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
10393                                 else
10394                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
10395                         }
10396                         break;
10397                 case TEXTURELAYERTYPE_TEXTURE:
10398                         // singletexture unlit texture with transparency support
10399                         R_Mesh_TexBind(0, layer->texture);
10400                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10401                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10402                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10403                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
10404                         break;
10405                 case TEXTURELAYERTYPE_FOG:
10406                         // singletexture fogging
10407                         if (layer->texture)
10408                         {
10409                                 R_Mesh_TexBind(0, layer->texture);
10410                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10411                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10412                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10413                         }
10414                         else
10415                         {
10416                                 R_Mesh_TexBind(0, 0);
10417                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10418                         }
10419                         // generate a color array for the fog pass
10420                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10421                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10422                         {
10423                                 int i;
10424                                 float f;
10425                                 const float *v;
10426                                 float *c;
10427                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10428                                 for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
10429                                 {
10430                                         f = 1 - RSurf_FogVertex(v);
10431                                         c[0] = layer->color[0];
10432                                         c[1] = layer->color[1];
10433                                         c[2] = layer->color[2];
10434                                         c[3] = f * layer->color[3];
10435                                 }
10436                         }
10437                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10438                         break;
10439                 default:
10440                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10441                 }
10442                 GL_LockArrays(0, 0);
10443         }
10444         CHECKGLERROR
10445         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10446         {
10447                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10448                 GL_AlphaTest(false);
10449         }
10450 }
10451
10452 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10453 {
10454         float c[4];
10455
10456         GL_AlphaTest(false);
10457         R_Mesh_ColorPointer(NULL, 0, 0);
10458         R_Mesh_ResetTextureState();
10459         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10460
10461         if(rsurface.texture && rsurface.texture->currentskinframe)
10462         {
10463                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10464                 c[3] *= rsurface.texture->currentalpha;
10465         }
10466         else
10467         {
10468                 c[0] = 1;
10469                 c[1] = 0;
10470                 c[2] = 1;
10471                 c[3] = 1;
10472         }
10473
10474         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10475         {
10476                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10477                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10478                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10479         }
10480
10481         // brighten it up (as texture value 127 means "unlit")
10482         c[0] *= 2 * r_refdef.view.colorscale;
10483         c[1] *= 2 * r_refdef.view.colorscale;
10484         c[2] *= 2 * r_refdef.view.colorscale;
10485
10486         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10487                 c[3] *= r_wateralpha.value;
10488
10489         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10490         {
10491                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10492                 GL_DepthMask(false);
10493         }
10494         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10495         {
10496                 GL_BlendFunc(GL_ONE, GL_ONE);
10497                 GL_DepthMask(false);
10498         }
10499         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10500         {
10501                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10502                 GL_DepthMask(false);
10503         }
10504         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10505         {
10506                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10507                 GL_DepthMask(false);
10508         }
10509         else
10510         {
10511                 GL_BlendFunc(GL_ONE, GL_ZERO);
10512                 GL_DepthMask(writedepth);
10513         }
10514
10515         rsurface.lightmapcolor4f = NULL;
10516
10517         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10518         {
10519                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10520
10521                 rsurface.lightmapcolor4f = NULL;
10522                 rsurface.lightmapcolor4f_bufferobject = 0;
10523                 rsurface.lightmapcolor4f_bufferoffset = 0;
10524         }
10525         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10526         {
10527                 qboolean applycolor = true;
10528                 float one = 1.0;
10529
10530                 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10531
10532                 r_refdef.lightmapintensity = 1;
10533                 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
10534                 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10535         }
10536         else
10537         {
10538                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10539
10540                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10541                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10542                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10543         }
10544
10545         if(!rsurface.lightmapcolor4f)
10546                 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
10547
10548         RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
10549         RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
10550         if(r_refdef.fogenabled)
10551                 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
10552
10553         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10554         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10555 }
10556
10557 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10558 {
10559         CHECKGLERROR
10560         RSurf_SetupDepthAndCulling();
10561         if (r_showsurfaces.integer == 3 && !prepass)
10562         {
10563                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10564                 return;
10565         }
10566         switch (vid.renderpath)
10567         {
10568         case RENDERPATH_GL20:
10569         case RENDERPATH_CGGL:
10570                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10571                 break;
10572         case RENDERPATH_GL13:
10573                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10574                 break;
10575         case RENDERPATH_GL11:
10576                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10577                 break;
10578         }
10579         CHECKGLERROR
10580 }
10581
10582 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10583 {
10584         CHECKGLERROR
10585         RSurf_SetupDepthAndCulling();
10586         if (r_showsurfaces.integer == 3 && !prepass)
10587         {
10588                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10589                 return;
10590         }
10591         switch (vid.renderpath)
10592         {
10593         case RENDERPATH_GL20:
10594         case RENDERPATH_CGGL:
10595                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10596                 break;
10597         case RENDERPATH_GL13:
10598                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10599                 break;
10600         case RENDERPATH_GL11:
10601                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10602                 break;
10603         }
10604         CHECKGLERROR
10605 }
10606
10607 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10608 {
10609         int i, j;
10610         int texturenumsurfaces, endsurface;
10611         texture_t *texture;
10612         const msurface_t *surface;
10613         const msurface_t *texturesurfacelist[256];
10614
10615         // if the model is static it doesn't matter what value we give for
10616         // wantnormals and wanttangents, so this logic uses only rules applicable
10617         // to a model, knowing that they are meaningless otherwise
10618         if (ent == r_refdef.scene.worldentity)
10619                 RSurf_ActiveWorldEntity();
10620         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10621                 RSurf_ActiveModelEntity(ent, false, false, false);
10622         else
10623         {
10624                 switch (vid.renderpath)
10625                 {
10626                 case RENDERPATH_GL20:
10627                 case RENDERPATH_CGGL:
10628                         RSurf_ActiveModelEntity(ent, true, true, false);
10629                         break;
10630                 case RENDERPATH_GL13:
10631                 case RENDERPATH_GL11:
10632                         RSurf_ActiveModelEntity(ent, true, false, false);
10633                         break;
10634                 }
10635         }
10636
10637         if (r_transparentdepthmasking.integer)
10638         {
10639                 qboolean setup = false;
10640                 for (i = 0;i < numsurfaces;i = j)
10641                 {
10642                         j = i + 1;
10643                         surface = rsurface.modelsurfaces + surfacelist[i];
10644                         texture = surface->texture;
10645                         rsurface.texture = R_GetCurrentTexture(texture);
10646                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10647                         // scan ahead until we find a different texture
10648                         endsurface = min(i + 1024, numsurfaces);
10649                         texturenumsurfaces = 0;
10650                         texturesurfacelist[texturenumsurfaces++] = surface;
10651                         for (;j < endsurface;j++)
10652                         {
10653                                 surface = rsurface.modelsurfaces + surfacelist[j];
10654                                 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10655                                         break;
10656                                 texturesurfacelist[texturenumsurfaces++] = surface;
10657                         }
10658                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10659                                 continue;
10660                         // render the range of surfaces as depth
10661                         if (!setup)
10662                         {
10663                                 setup = true;
10664                                 GL_ColorMask(0,0,0,0);
10665                                 GL_Color(1,1,1,1);
10666                                 GL_DepthTest(true);
10667                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10668                                 GL_DepthMask(true);
10669                                 GL_AlphaTest(false);
10670                                 R_Mesh_ColorPointer(NULL, 0, 0);
10671                                 R_Mesh_ResetTextureState();
10672                                 R_SetupShader_DepthOrShadow();
10673                         }
10674                         RSurf_SetupDepthAndCulling();
10675                         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10676                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10677                 }
10678                 if (setup)
10679                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10680         }
10681
10682         for (i = 0;i < numsurfaces;i = j)
10683         {
10684                 j = i + 1;
10685                 surface = rsurface.modelsurfaces + surfacelist[i];
10686                 texture = surface->texture;
10687                 rsurface.texture = R_GetCurrentTexture(texture);
10688                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10689                 // scan ahead until we find a different texture
10690                 endsurface = min(i + 1024, numsurfaces);
10691                 texturenumsurfaces = 0;
10692                 texturesurfacelist[texturenumsurfaces++] = surface;
10693                 for (;j < endsurface;j++)
10694                 {
10695                         surface = rsurface.modelsurfaces + surfacelist[j];
10696                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10697                                 break;
10698                         texturesurfacelist[texturenumsurfaces++] = surface;
10699                 }
10700                 // render the range of surfaces
10701                 if (ent == r_refdef.scene.worldentity)
10702                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10703                 else
10704                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10705         }
10706         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10707         GL_AlphaTest(false);
10708 }
10709
10710 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10711 {
10712         // transparent surfaces get pushed off into the transparent queue
10713         int surfacelistindex;
10714         const msurface_t *surface;
10715         vec3_t tempcenter, center;
10716         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10717         {
10718                 surface = texturesurfacelist[surfacelistindex];
10719                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10720                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10721                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10722                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10723                 if (queueentity->transparent_offset) // transparent offset
10724                 {
10725                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10726                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10727                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10728                 }
10729                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10730         }
10731 }
10732
10733 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10734 {
10735         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10736         CHECKGLERROR
10737         if (depthonly)
10738         {
10739                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10740                         return;
10741                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10742                         return;
10743                 RSurf_SetupDepthAndCulling();
10744                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10745                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10746         }
10747         else if (prepass)
10748         {
10749                 if (!rsurface.texture->currentnumlayers)
10750                         return;
10751                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10752                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10753                 else
10754                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10755         }
10756         else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
10757         {
10758                 RSurf_SetupDepthAndCulling();
10759                 GL_AlphaTest(false);
10760                 R_Mesh_ColorPointer(NULL, 0, 0);
10761                 R_Mesh_ResetTextureState();
10762                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10763                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10764                 GL_DepthMask(true);
10765                 GL_BlendFunc(GL_ONE, GL_ZERO);
10766                 GL_Color(0, 0, 0, 1);
10767                 GL_DepthTest(writedepth);
10768                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10769         }
10770         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
10771         {
10772                 RSurf_SetupDepthAndCulling();
10773                 GL_AlphaTest(false);
10774                 R_Mesh_ColorPointer(NULL, 0, 0);
10775                 R_Mesh_ResetTextureState();
10776                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10777                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10778                 GL_DepthMask(true);
10779                 GL_BlendFunc(GL_ONE, GL_ZERO);
10780                 GL_DepthTest(true);
10781                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
10782         }
10783         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
10784                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10785         else if (!rsurface.texture->currentnumlayers)
10786                 return;
10787         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10788         {
10789                 // in the deferred case, transparent surfaces were queued during prepass
10790                 if (!r_shadow_usingdeferredprepass)
10791                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10792         }
10793         else
10794         {
10795                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10796                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10797         }
10798         CHECKGLERROR
10799 }
10800
10801 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10802 {
10803         int i, j;
10804         texture_t *texture;
10805         // break the surface list down into batches by texture and use of lightmapping
10806         for (i = 0;i < numsurfaces;i = j)
10807         {
10808                 j = i + 1;
10809                 // texture is the base texture pointer, rsurface.texture is the
10810                 // current frame/skin the texture is directing us to use (for example
10811                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10812                 // use skin 1 instead)
10813                 texture = surfacelist[i]->texture;
10814                 rsurface.texture = R_GetCurrentTexture(texture);
10815                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
10816                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10817                 {
10818                         // if this texture is not the kind we want, skip ahead to the next one
10819                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10820                                 ;
10821                         continue;
10822                 }
10823                 // simply scan ahead until we find a different texture or lightmap state
10824                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
10825                         ;
10826                 // render the range of surfaces
10827                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10828         }
10829 }
10830
10831 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10832 {
10833         CHECKGLERROR
10834         if (depthonly)
10835         {
10836                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10837                         return;
10838                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10839                         return;
10840                 RSurf_SetupDepthAndCulling();
10841                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10842                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10843         }
10844         else if (prepass)
10845         {
10846                 if (!rsurface.texture->currentnumlayers)
10847                         return;
10848                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10849                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10850                 else
10851                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10852         }
10853         else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
10854         {
10855                 RSurf_SetupDepthAndCulling();
10856                 GL_AlphaTest(false);
10857                 R_Mesh_ColorPointer(NULL, 0, 0);
10858                 R_Mesh_ResetTextureState();
10859                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10860                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10861                 GL_DepthMask(true);
10862                 GL_BlendFunc(GL_ONE, GL_ZERO);
10863                 GL_Color(0, 0, 0, 1);
10864                 GL_DepthTest(writedepth);
10865                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10866         }
10867         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10868         {
10869                 RSurf_SetupDepthAndCulling();
10870                 GL_AlphaTest(false);
10871                 R_Mesh_ColorPointer(NULL, 0, 0);
10872                 R_Mesh_ResetTextureState();
10873                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10874                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10875                 GL_DepthMask(true);
10876                 GL_BlendFunc(GL_ONE, GL_ZERO);
10877                 GL_DepthTest(true);
10878                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
10879         }
10880         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
10881                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10882         else if (!rsurface.texture->currentnumlayers)
10883                 return;
10884         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10885         {
10886                 // in the deferred case, transparent surfaces were queued during prepass
10887                 if (!r_shadow_usingdeferredprepass)
10888                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10889         }
10890         else
10891         {
10892                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10893                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10894         }
10895         CHECKGLERROR
10896 }
10897
10898 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10899 {
10900         int i, j;
10901         texture_t *texture;
10902         // break the surface list down into batches by texture and use of lightmapping
10903         for (i = 0;i < numsurfaces;i = j)
10904         {
10905                 j = i + 1;
10906                 // texture is the base texture pointer, rsurface.texture is the
10907                 // current frame/skin the texture is directing us to use (for example
10908                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10909                 // use skin 1 instead)
10910                 texture = surfacelist[i]->texture;
10911                 rsurface.texture = R_GetCurrentTexture(texture);
10912                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
10913                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10914                 {
10915                         // if this texture is not the kind we want, skip ahead to the next one
10916                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10917                                 ;
10918                         continue;
10919                 }
10920                 // simply scan ahead until we find a different texture or lightmap state
10921                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
10922                         ;
10923                 // render the range of surfaces
10924                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10925         }
10926 }
10927
10928 float locboxvertex3f[6*4*3] =
10929 {
10930         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10931         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10932         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10933         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10934         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10935         1,0,0, 0,0,0, 0,1,0, 1,1,0
10936 };
10937
10938 unsigned short locboxelements[6*2*3] =
10939 {
10940          0, 1, 2, 0, 2, 3,
10941          4, 5, 6, 4, 6, 7,
10942          8, 9,10, 8,10,11,
10943         12,13,14, 12,14,15,
10944         16,17,18, 16,18,19,
10945         20,21,22, 20,22,23
10946 };
10947
10948 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10949 {
10950         int i, j;
10951         cl_locnode_t *loc = (cl_locnode_t *)ent;
10952         vec3_t mins, size;
10953         float vertex3f[6*4*3];
10954         CHECKGLERROR
10955         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10956         GL_DepthMask(false);
10957         GL_DepthRange(0, 1);
10958         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10959         GL_DepthTest(true);
10960         GL_CullFace(GL_NONE);
10961         R_EntityMatrix(&identitymatrix);
10962
10963         R_Mesh_VertexPointer(vertex3f, 0, 0);
10964         R_Mesh_ColorPointer(NULL, 0, 0);
10965         R_Mesh_ResetTextureState();
10966         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10967
10968         i = surfacelist[0];
10969         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10970                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10971                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10972                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10973
10974         if (VectorCompare(loc->mins, loc->maxs))
10975         {
10976                 VectorSet(size, 2, 2, 2);
10977                 VectorMA(loc->mins, -0.5f, size, mins);
10978         }
10979         else
10980         {
10981                 VectorCopy(loc->mins, mins);
10982                 VectorSubtract(loc->maxs, loc->mins, size);
10983         }
10984
10985         for (i = 0;i < 6*4*3;)
10986                 for (j = 0;j < 3;j++, i++)
10987                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10988
10989         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
10990 }
10991
10992 void R_DrawLocs(void)
10993 {
10994         int index;
10995         cl_locnode_t *loc, *nearestloc;
10996         vec3_t center;
10997         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10998         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10999         {
11000                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11001                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11002         }
11003 }
11004
11005 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11006 {
11007         if (decalsystem->decals)
11008                 Mem_Free(decalsystem->decals);
11009         memset(decalsystem, 0, sizeof(*decalsystem));
11010 }
11011
11012 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)
11013 {
11014         tridecal_t *decal;
11015         tridecal_t *decals;
11016         int i;
11017         int maxdecals;
11018
11019         // expand or initialize the system
11020         if (decalsystem->maxdecals <= decalsystem->numdecals)
11021         {
11022                 decalsystem_t old = *decalsystem;
11023                 qboolean useshortelements;
11024                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11025                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11026                 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)));
11027                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11028                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11029                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11030                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11031                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11032                 if (decalsystem->numdecals)
11033                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11034                 if (old.decals)
11035                         Mem_Free(old.decals);
11036                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11037                         decalsystem->element3i[i] = i;
11038                 if (useshortelements)
11039                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11040                                 decalsystem->element3s[i] = i;
11041         }
11042
11043         // grab a decal and search for another free slot for the next one
11044         maxdecals = decalsystem->maxdecals;
11045         decals = decalsystem->decals;
11046         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11047         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
11048                 ;
11049         decalsystem->freedecal = i;
11050         if (decalsystem->numdecals <= i)
11051                 decalsystem->numdecals = i + 1;
11052
11053         // initialize the decal
11054         decal->lived = 0;
11055         decal->triangleindex = triangleindex;
11056         decal->surfaceindex = surfaceindex;
11057         decal->decalsequence = decalsequence;
11058         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
11059         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
11060         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
11061         decal->color4ub[0][3] = 255;
11062         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
11063         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
11064         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
11065         decal->color4ub[1][3] = 255;
11066         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
11067         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
11068         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
11069         decal->color4ub[2][3] = 255;
11070         decal->vertex3f[0][0] = v0[0];
11071         decal->vertex3f[0][1] = v0[1];
11072         decal->vertex3f[0][2] = v0[2];
11073         decal->vertex3f[1][0] = v1[0];
11074         decal->vertex3f[1][1] = v1[1];
11075         decal->vertex3f[1][2] = v1[2];
11076         decal->vertex3f[2][0] = v2[0];
11077         decal->vertex3f[2][1] = v2[1];
11078         decal->vertex3f[2][2] = v2[2];
11079         decal->texcoord2f[0][0] = t0[0];
11080         decal->texcoord2f[0][1] = t0[1];
11081         decal->texcoord2f[1][0] = t1[0];
11082         decal->texcoord2f[1][1] = t1[1];
11083         decal->texcoord2f[2][0] = t2[0];
11084         decal->texcoord2f[2][1] = t2[1];
11085 }
11086
11087 extern cvar_t cl_decals_bias;
11088 extern cvar_t cl_decals_models;
11089 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11090 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)
11091 {
11092         matrix4x4_t projection;
11093         decalsystem_t *decalsystem;
11094         qboolean dynamic;
11095         dp_model_t *model;
11096         const float *vertex3f;
11097         const msurface_t *surface;
11098         const msurface_t *surfaces;
11099         const int *surfacelist;
11100         const texture_t *texture;
11101         int numvertices;
11102         int numtriangles;
11103         int numsurfacelist;
11104         int surfacelistindex;
11105         int surfaceindex;
11106         int triangleindex;
11107         int decalsurfaceindex;
11108         int cornerindex;
11109         int index;
11110         int numpoints;
11111         const int *e;
11112         float localorigin[3];
11113         float localnormal[3];
11114         float localmins[3];
11115         float localmaxs[3];
11116         float localsize;
11117         float ilocalsize;
11118         float v[9][3];
11119         float tc[9][2];
11120         float c[9][4];
11121         //float normal[3];
11122         float planes[6][4];
11123         float f;
11124         float points[2][9][3];
11125         float angles[3];
11126         float temp[3];
11127
11128         decalsystem = &ent->decalsystem;
11129         model = ent->model;
11130         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11131         {
11132                 R_DecalSystem_Reset(&ent->decalsystem);
11133                 return;
11134         }
11135
11136         if (!model->brush.data_nodes && !cl_decals_models.integer)
11137         {
11138                 if (decalsystem->model)
11139                         R_DecalSystem_Reset(decalsystem);
11140                 return;
11141         }
11142
11143         if (decalsystem->model != model)
11144                 R_DecalSystem_Reset(decalsystem);
11145         decalsystem->model = model;
11146
11147         RSurf_ActiveModelEntity(ent, false, false, false);
11148
11149         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11150         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11151         VectorNormalize(localnormal);
11152         localsize = worldsize*rsurface.inversematrixscale;
11153         ilocalsize = 1.0f / localsize;
11154         localmins[0] = localorigin[0] - localsize;
11155         localmins[1] = localorigin[1] - localsize;
11156         localmins[2] = localorigin[2] - localsize;
11157         localmaxs[0] = localorigin[0] + localsize;
11158         localmaxs[1] = localorigin[1] + localsize;
11159         localmaxs[2] = localorigin[2] + localsize;
11160
11161         //VectorCopy(localnormal, planes[4]);
11162         //VectorVectors(planes[4], planes[2], planes[0]);
11163         AnglesFromVectors(angles, localnormal, NULL, false);
11164         AngleVectors(angles, planes[0], planes[2], planes[4]);
11165         VectorNegate(planes[0], planes[1]);
11166         VectorNegate(planes[2], planes[3]);
11167         VectorNegate(planes[4], planes[5]);
11168         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11169         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11170         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11171         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11172         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11173         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11174
11175 #if 1
11176 // works
11177 {
11178         matrix4x4_t forwardprojection;
11179         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11180         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11181 }
11182 #else
11183 // broken
11184 {
11185         float projectionvector[4][3];
11186         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11187         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11188         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11189         projectionvector[0][0] = planes[0][0] * ilocalsize;
11190         projectionvector[0][1] = planes[1][0] * ilocalsize;
11191         projectionvector[0][2] = planes[2][0] * ilocalsize;
11192         projectionvector[1][0] = planes[0][1] * ilocalsize;
11193         projectionvector[1][1] = planes[1][1] * ilocalsize;
11194         projectionvector[1][2] = planes[2][1] * ilocalsize;
11195         projectionvector[2][0] = planes[0][2] * ilocalsize;
11196         projectionvector[2][1] = planes[1][2] * ilocalsize;
11197         projectionvector[2][2] = planes[2][2] * ilocalsize;
11198         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11199         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11200         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11201         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11202 }
11203 #endif
11204
11205         dynamic = model->surfmesh.isanimated;
11206         vertex3f = rsurface.modelvertex3f;
11207         numsurfacelist = model->nummodelsurfaces;
11208         surfacelist = model->sortedmodelsurfaces;
11209         surfaces = model->data_surfaces;
11210         for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11211         {
11212                 surfaceindex = surfacelist[surfacelistindex];
11213                 surface = surfaces + surfaceindex;
11214                 // skip transparent surfaces
11215                 texture = surface->texture;
11216                 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11217                         continue;
11218                 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11219                         continue;
11220                 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11221                         continue;
11222                 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
11223                 numvertices = surface->num_vertices;
11224                 numtriangles = surface->num_triangles;
11225                 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
11226                 {
11227                         for (cornerindex = 0;cornerindex < 3;cornerindex++)
11228                         {
11229                                 index = 3*e[cornerindex];
11230                                 VectorCopy(vertex3f + index, v[cornerindex]);
11231                         }
11232                         // cull backfaces
11233                         //TriangleNormal(v[0], v[1], v[2], normal);
11234                         //if (DotProduct(normal, localnormal) < 0.0f)
11235                         //      continue;
11236                         // clip by each of the box planes formed from the projection matrix
11237                         // if anything survives, we emit the decal
11238                         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]);
11239                         if (numpoints < 3)
11240                                 continue;
11241                         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]);
11242                         if (numpoints < 3)
11243                                 continue;
11244                         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]);
11245                         if (numpoints < 3)
11246                                 continue;
11247                         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]);
11248                         if (numpoints < 3)
11249                                 continue;
11250                         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]);
11251                         if (numpoints < 3)
11252                                 continue;
11253                         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]);
11254                         if (numpoints < 3)
11255                                 continue;
11256                         // some part of the triangle survived, so we have to accept it...
11257                         if (dynamic)
11258                         {
11259                                 // dynamic always uses the original triangle
11260                                 numpoints = 3;
11261                                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11262                                 {
11263                                         index = 3*e[cornerindex];
11264                                         VectorCopy(vertex3f + index, v[cornerindex]);
11265                                 }
11266                         }
11267                         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11268                         {
11269                                 // convert vertex positions to texcoords
11270                                 Matrix4x4_Transform(&projection, v[cornerindex], temp);
11271                                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11272                                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11273                                 // calculate distance fade from the projection origin
11274                                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11275                                 f = bound(0.0f, f, 1.0f);
11276                                 c[cornerindex][0] = r * f;
11277                                 c[cornerindex][1] = g * f;
11278                                 c[cornerindex][2] = b * f;
11279                                 c[cornerindex][3] = 1.0f;
11280                                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11281                         }
11282                         if (dynamic)
11283                                 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);
11284                         else
11285                                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11286                                         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);
11287                 }
11288         }
11289 }
11290
11291 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11292 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)
11293 {
11294         int renderentityindex;
11295         float worldmins[3];
11296         float worldmaxs[3];
11297         entity_render_t *ent;
11298
11299         if (!cl_decals_newsystem.integer)
11300                 return;
11301
11302         worldmins[0] = worldorigin[0] - worldsize;
11303         worldmins[1] = worldorigin[1] - worldsize;
11304         worldmins[2] = worldorigin[2] - worldsize;
11305         worldmaxs[0] = worldorigin[0] + worldsize;
11306         worldmaxs[1] = worldorigin[1] + worldsize;
11307         worldmaxs[2] = worldorigin[2] + worldsize;
11308
11309         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11310
11311         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11312         {
11313                 ent = r_refdef.scene.entities[renderentityindex];
11314                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11315                         continue;
11316
11317                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11318         }
11319 }
11320
11321 typedef struct r_decalsystem_splatqueue_s
11322 {
11323         vec3_t worldorigin;
11324         vec3_t worldnormal;
11325         float color[4];
11326         float tcrange[4];
11327         float worldsize;
11328         int decalsequence;
11329 }
11330 r_decalsystem_splatqueue_t;
11331
11332 int r_decalsystem_numqueued = 0;
11333 #define MAX_DECALSYSTEM_QUEUE 1024
11334 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11335
11336 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)
11337 {
11338         r_decalsystem_splatqueue_t *queue;
11339
11340         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11341                 return;
11342
11343         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11344         VectorCopy(worldorigin, queue->worldorigin);
11345         VectorCopy(worldnormal, queue->worldnormal);
11346         Vector4Set(queue->color, r, g, b, a);
11347         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11348         queue->worldsize = worldsize;
11349         queue->decalsequence = cl.decalsequence++;
11350 }
11351
11352 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11353 {
11354         int i;
11355         r_decalsystem_splatqueue_t *queue;
11356
11357         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11358                 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);
11359         r_decalsystem_numqueued = 0;
11360 }
11361
11362 extern cvar_t cl_decals_max;
11363 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11364 {
11365         int i;
11366         decalsystem_t *decalsystem = &ent->decalsystem;
11367         int numdecals;
11368         int killsequence;
11369         tridecal_t *decal;
11370         float frametime;
11371         float lifetime;
11372
11373         if (!decalsystem->numdecals)
11374                 return;
11375
11376         if (r_showsurfaces.integer)
11377                 return;
11378
11379         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11380         {
11381                 R_DecalSystem_Reset(decalsystem);
11382                 return;
11383         }
11384
11385         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11386         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11387
11388         if (decalsystem->lastupdatetime)
11389                 frametime = (cl.time - decalsystem->lastupdatetime);
11390         else
11391                 frametime = 0;
11392         decalsystem->lastupdatetime = cl.time;
11393         decal = decalsystem->decals;
11394         numdecals = decalsystem->numdecals;
11395
11396         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11397         {
11398                 if (decal->color4ub[0][3])
11399                 {
11400                         decal->lived += frametime;
11401                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11402                         {
11403                                 memset(decal, 0, sizeof(*decal));
11404                                 if (decalsystem->freedecal > i)
11405                                         decalsystem->freedecal = i;
11406                         }
11407                 }
11408         }
11409         decal = decalsystem->decals;
11410         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
11411                 numdecals--;
11412
11413         // collapse the array by shuffling the tail decals into the gaps
11414         for (;;)
11415         {
11416                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
11417                         decalsystem->freedecal++;
11418                 if (decalsystem->freedecal == numdecals)
11419                         break;
11420                 decal[decalsystem->freedecal] = decal[--numdecals];
11421         }
11422
11423         decalsystem->numdecals = numdecals;
11424
11425         if (numdecals <= 0)
11426         {
11427                 // if there are no decals left, reset decalsystem
11428                 R_DecalSystem_Reset(decalsystem);
11429         }
11430 }
11431
11432 extern skinframe_t *decalskinframe;
11433 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11434 {
11435         int i;
11436         decalsystem_t *decalsystem = &ent->decalsystem;
11437         int numdecals;
11438         tridecal_t *decal;
11439         float fadedelay;
11440         float faderate;
11441         float alpha;
11442         float *v3f;
11443         float *c4f;
11444         float *t2f;
11445         const int *e;
11446         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11447         int numtris = 0;
11448
11449         numdecals = decalsystem->numdecals;
11450         if (!numdecals)
11451                 return;
11452
11453         if (r_showsurfaces.integer)
11454                 return;
11455
11456         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11457         {
11458                 R_DecalSystem_Reset(decalsystem);
11459                 return;
11460         }
11461
11462         // if the model is static it doesn't matter what value we give for
11463         // wantnormals and wanttangents, so this logic uses only rules applicable
11464         // to a model, knowing that they are meaningless otherwise
11465         if (ent == r_refdef.scene.worldentity)
11466                 RSurf_ActiveWorldEntity();
11467         else
11468                 RSurf_ActiveModelEntity(ent, false, false, false);
11469
11470         decalsystem->lastupdatetime = cl.time;
11471         decal = decalsystem->decals;
11472
11473         fadedelay = cl_decals_time.value;
11474         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11475
11476         // update vertex positions for animated models
11477         v3f = decalsystem->vertex3f;
11478         c4f = decalsystem->color4f;
11479         t2f = decalsystem->texcoord2f;
11480         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11481         {
11482                 if (!decal->color4ub[0][3])
11483                         continue;
11484
11485                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11486                         continue;
11487
11488                 // update color values for fading decals
11489                 if (decal->lived >= cl_decals_time.value)
11490                 {
11491                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11492                         alpha *= (1.0f/255.0f);
11493                 }
11494                 else
11495                         alpha = 1.0f/255.0f;
11496
11497                 c4f[ 0] = decal->color4ub[0][0] * alpha;
11498                 c4f[ 1] = decal->color4ub[0][1] * alpha;
11499                 c4f[ 2] = decal->color4ub[0][2] * alpha;
11500                 c4f[ 3] = 1;
11501                 c4f[ 4] = decal->color4ub[1][0] * alpha;
11502                 c4f[ 5] = decal->color4ub[1][1] * alpha;
11503                 c4f[ 6] = decal->color4ub[1][2] * alpha;
11504                 c4f[ 7] = 1;
11505                 c4f[ 8] = decal->color4ub[2][0] * alpha;
11506                 c4f[ 9] = decal->color4ub[2][1] * alpha;
11507                 c4f[10] = decal->color4ub[2][2] * alpha;
11508                 c4f[11] = 1;
11509
11510                 t2f[0] = decal->texcoord2f[0][0];
11511                 t2f[1] = decal->texcoord2f[0][1];
11512                 t2f[2] = decal->texcoord2f[1][0];
11513                 t2f[3] = decal->texcoord2f[1][1];
11514                 t2f[4] = decal->texcoord2f[2][0];
11515                 t2f[5] = decal->texcoord2f[2][1];
11516
11517                 // update vertex positions for animated models
11518                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
11519                 {
11520                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11521                         VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
11522                         VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
11523                         VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
11524                 }
11525                 else
11526                 {
11527                         VectorCopy(decal->vertex3f[0], v3f);
11528                         VectorCopy(decal->vertex3f[1], v3f + 3);
11529                         VectorCopy(decal->vertex3f[2], v3f + 6);
11530                 }
11531
11532                 v3f += 9;
11533                 c4f += 12;
11534                 t2f += 6;
11535                 numtris++;
11536         }
11537
11538         if (numtris > 0)
11539         {
11540                 r_refdef.stats.drawndecals += numtris;
11541
11542                 if (r_refdef.fogenabled)
11543                 {
11544                         switch(vid.renderpath)
11545                         {
11546                         case RENDERPATH_GL20:
11547                         case RENDERPATH_CGGL:
11548                         case RENDERPATH_GL13:
11549                         case RENDERPATH_GL11:
11550                                 for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
11551                                 {
11552                                         alpha = RSurf_FogVertex(v3f);
11553                                         c4f[0] *= alpha;
11554                                         c4f[1] *= alpha;
11555                                         c4f[2] *= alpha;
11556                                 }
11557                                 break;
11558                         }
11559                 }
11560
11561                 // now render the decals all at once
11562                 // (this assumes they all use one particle font texture!)
11563                 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);
11564                 R_Mesh_ResetTextureState();
11565                 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
11566                 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
11567                 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
11568                 GL_DepthMask(false);
11569                 GL_DepthRange(0, 1);
11570                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11571                 GL_DepthTest(true);
11572                 GL_CullFace(GL_NONE);
11573                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11574                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
11575                 GL_LockArrays(0, numtris * 3);
11576                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
11577                 GL_LockArrays(0, 0);
11578         }
11579 }
11580
11581 static void R_DrawModelDecals(void)
11582 {
11583         int i, numdecals;
11584
11585         // fade faster when there are too many decals
11586         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11587         for (i = 0;i < r_refdef.scene.numentities;i++)
11588                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11589
11590         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11591         for (i = 0;i < r_refdef.scene.numentities;i++)
11592                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11593                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11594
11595         R_DecalSystem_ApplySplatEntitiesQueue();
11596
11597         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11598         for (i = 0;i < r_refdef.scene.numentities;i++)
11599                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11600
11601         r_refdef.stats.totaldecals += numdecals;
11602
11603         if (r_showsurfaces.integer)
11604                 return;
11605
11606         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11607
11608         for (i = 0;i < r_refdef.scene.numentities;i++)
11609         {
11610                 if (!r_refdef.viewcache.entityvisible[i])
11611                         continue;
11612                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11613                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11614         }
11615 }
11616
11617 void R_DrawDebugModel(void)
11618 {
11619         entity_render_t *ent = rsurface.entity;
11620         int i, j, k, l, flagsmask;
11621         const int *elements;
11622         q3mbrush_t *brush;
11623         const msurface_t *surface;
11624         dp_model_t *model = ent->model;
11625         vec3_t v;
11626
11627         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11628
11629         R_Mesh_ColorPointer(NULL, 0, 0);
11630         R_Mesh_ResetTextureState();
11631         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11632         GL_DepthRange(0, 1);
11633         GL_DepthTest(!r_showdisabledepthtest.integer);
11634         GL_DepthMask(false);
11635         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11636
11637         if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
11638         {
11639                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11640                 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
11641                 {
11642                         if (brush->colbrushf && brush->colbrushf->numtriangles)
11643                         {
11644                                 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
11645                                 GL_Color((i & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
11646                                 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
11647                         }
11648                 }
11649                 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
11650                 {
11651                         if (surface->num_collisiontriangles)
11652                         {
11653                                 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
11654                                 GL_Color((i & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
11655                                 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
11656                         }
11657                 }
11658         }
11659
11660         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11661
11662         if (r_showtris.integer || r_shownormals.integer)
11663         {
11664                 if (r_showdisabledepthtest.integer)
11665                 {
11666                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11667                         GL_DepthMask(false);
11668                 }
11669                 else
11670                 {
11671                         GL_BlendFunc(GL_ONE, GL_ZERO);
11672                         GL_DepthMask(true);
11673                 }
11674                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11675                 {
11676                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11677                                 continue;
11678                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11679                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11680                         {
11681                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
11682                                 if (r_showtris.value > 0)
11683                                 {
11684                                         if (!rsurface.texture->currentlayers->depthmask)
11685                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11686                                         else if (ent == r_refdef.scene.worldentity)
11687                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11688                                         else
11689                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11690                                         elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
11691                                         R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
11692                                         R_Mesh_ColorPointer(NULL, 0, 0);
11693                                         R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
11694                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11695                                         //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
11696                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
11697                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11698                                         CHECKGLERROR
11699                                 }
11700                                 if (r_shownormals.value < 0)
11701                                 {
11702                                         qglBegin(GL_LINES);
11703                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11704                                         {
11705                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11706                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11707                                                 qglVertex3f(v[0], v[1], v[2]);
11708                                                 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
11709                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11710                                                 qglVertex3f(v[0], v[1], v[2]);
11711                                         }
11712                                         qglEnd();
11713                                         CHECKGLERROR
11714                                 }
11715                                 if (r_shownormals.value > 0)
11716                                 {
11717                                         qglBegin(GL_LINES);
11718                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11719                                         {
11720                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11721                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11722                                                 qglVertex3f(v[0], v[1], v[2]);
11723                                                 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
11724                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11725                                                 qglVertex3f(v[0], v[1], v[2]);
11726                                         }
11727                                         qglEnd();
11728                                         CHECKGLERROR
11729                                         qglBegin(GL_LINES);
11730                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11731                                         {
11732                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11733                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11734                                                 qglVertex3f(v[0], v[1], v[2]);
11735                                                 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
11736                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11737                                                 qglVertex3f(v[0], v[1], v[2]);
11738                                         }
11739                                         qglEnd();
11740                                         CHECKGLERROR
11741                                         qglBegin(GL_LINES);
11742                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11743                                         {
11744                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11745                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11746                                                 qglVertex3f(v[0], v[1], v[2]);
11747                                                 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
11748                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11749                                                 qglVertex3f(v[0], v[1], v[2]);
11750                                         }
11751                                         qglEnd();
11752                                         CHECKGLERROR
11753                                 }
11754                         }
11755                 }
11756                 rsurface.texture = NULL;
11757         }
11758 }
11759
11760 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11761 int r_maxsurfacelist = 0;
11762 const msurface_t **r_surfacelist = NULL;
11763 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11764 {
11765         int i, j, endj, f, flagsmask;
11766         texture_t *t;
11767         dp_model_t *model = r_refdef.scene.worldmodel;
11768         msurface_t *surfaces;
11769         unsigned char *update;
11770         int numsurfacelist = 0;
11771         if (model == NULL)
11772                 return;
11773
11774         if (r_maxsurfacelist < model->num_surfaces)
11775         {
11776                 r_maxsurfacelist = model->num_surfaces;
11777                 if (r_surfacelist)
11778                         Mem_Free((msurface_t**)r_surfacelist);
11779                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11780         }
11781
11782         RSurf_ActiveWorldEntity();
11783
11784         surfaces = model->data_surfaces;
11785         update = model->brushq1.lightmapupdateflags;
11786
11787         // update light styles on this submodel
11788         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11789         {
11790                 model_brush_lightstyleinfo_t *style;
11791                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11792                 {
11793                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11794                         {
11795                                 int *list = style->surfacelist;
11796                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11797                                 for (j = 0;j < style->numsurfaces;j++)
11798                                         update[list[j]] = true;
11799                         }
11800                 }
11801         }
11802
11803         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11804
11805         if (debug)
11806         {
11807                 R_DrawDebugModel();
11808                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11809                 return;
11810         }
11811
11812         f = 0;
11813         t = NULL;
11814         rsurface.uselightmaptexture = false;
11815         rsurface.texture = NULL;
11816         rsurface.rtlight = NULL;
11817         numsurfacelist = 0;
11818         // add visible surfaces to draw list
11819         for (i = 0;i < model->nummodelsurfaces;i++)
11820         {
11821                 j = model->sortedmodelsurfaces[i];
11822                 if (r_refdef.viewcache.world_surfacevisible[j])
11823                         r_surfacelist[numsurfacelist++] = surfaces + j;
11824         }
11825         // update lightmaps if needed
11826         if (update)
11827         {
11828                 int updated = 0;
11829                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11830                 {
11831                         if (r_refdef.viewcache.world_surfacevisible[j])
11832                         {
11833                                 if (update[j])
11834                                 {
11835                                         updated++;
11836                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11837                                 }
11838                         }
11839                 }
11840         }
11841         // don't do anything if there were no surfaces
11842         if (!numsurfacelist)
11843         {
11844                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11845                 return;
11846         }
11847         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11848         GL_AlphaTest(false);
11849
11850         // add to stats if desired
11851         if (r_speeds.integer && !skysurfaces && !depthonly)
11852         {
11853                 r_refdef.stats.world_surfaces += numsurfacelist;
11854                 for (j = 0;j < numsurfacelist;j++)
11855                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11856         }
11857
11858         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11859 }
11860
11861 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11862 {
11863         int i, j, endj, f, flagsmask;
11864         texture_t *t;
11865         dp_model_t *model = ent->model;
11866         msurface_t *surfaces;
11867         unsigned char *update;
11868         int numsurfacelist = 0;
11869         if (model == NULL)
11870                 return;
11871
11872         if (r_maxsurfacelist < model->num_surfaces)
11873         {
11874                 r_maxsurfacelist = model->num_surfaces;
11875                 if (r_surfacelist)
11876                         Mem_Free((msurface_t **)r_surfacelist);
11877                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11878         }
11879
11880         // if the model is static it doesn't matter what value we give for
11881         // wantnormals and wanttangents, so this logic uses only rules applicable
11882         // to a model, knowing that they are meaningless otherwise
11883         if (ent == r_refdef.scene.worldentity)
11884                 RSurf_ActiveWorldEntity();
11885         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11886                 RSurf_ActiveModelEntity(ent, false, false, false);
11887         else if (prepass)
11888                 RSurf_ActiveModelEntity(ent, true, true, true);
11889         else if (depthonly)
11890                 RSurf_ActiveModelEntity(ent, false, false, false);
11891         else
11892         {
11893                 switch (vid.renderpath)
11894                 {
11895                 case RENDERPATH_GL20:
11896                 case RENDERPATH_CGGL:
11897                         RSurf_ActiveModelEntity(ent, true, true, false);
11898                         break;
11899                 case RENDERPATH_GL13:
11900                 case RENDERPATH_GL11:
11901                         RSurf_ActiveModelEntity(ent, true, false, false);
11902                         break;
11903                 }
11904         }
11905
11906         surfaces = model->data_surfaces;
11907         update = model->brushq1.lightmapupdateflags;
11908
11909         // update light styles
11910         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11911         {
11912                 model_brush_lightstyleinfo_t *style;
11913                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11914                 {
11915                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11916                         {
11917                                 int *list = style->surfacelist;
11918                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11919                                 for (j = 0;j < style->numsurfaces;j++)
11920                                         update[list[j]] = true;
11921                         }
11922                 }
11923         }
11924
11925         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11926
11927         if (debug)
11928         {
11929                 R_DrawDebugModel();
11930                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11931                 return;
11932         }
11933
11934         f = 0;
11935         t = NULL;
11936         rsurface.uselightmaptexture = false;
11937         rsurface.texture = NULL;
11938         rsurface.rtlight = NULL;
11939         numsurfacelist = 0;
11940         // add visible surfaces to draw list
11941         for (i = 0;i < model->nummodelsurfaces;i++)
11942                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11943         // don't do anything if there were no surfaces
11944         if (!numsurfacelist)
11945         {
11946                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11947                 return;
11948         }
11949         // update lightmaps if needed
11950         if (update)
11951         {
11952                 int updated = 0;
11953                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11954                 {
11955                         if (update[j])
11956                         {
11957                                 updated++;
11958                                 R_BuildLightMap(ent, surfaces + j);
11959                         }
11960                 }
11961         }
11962         if (update)
11963                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11964                         if (update[j])
11965                                 R_BuildLightMap(ent, surfaces + j);
11966         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11967         GL_AlphaTest(false);
11968
11969         // add to stats if desired
11970         if (r_speeds.integer && !skysurfaces && !depthonly)
11971         {
11972                 r_refdef.stats.entities_surfaces += numsurfacelist;
11973                 for (j = 0;j < numsurfacelist;j++)
11974                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11975         }
11976
11977         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11978 }
11979
11980 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11981 {
11982         static texture_t texture;
11983         static msurface_t surface;
11984         const msurface_t *surfacelist = &surface;
11985
11986         // fake enough texture and surface state to render this geometry
11987
11988         texture.update_lastrenderframe = -1; // regenerate this texture
11989         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11990         texture.currentskinframe = skinframe;
11991         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11992         texture.specularscalemod = 1;
11993         texture.specularpowermod = 1;
11994
11995         surface.texture = &texture;
11996         surface.num_triangles = numtriangles;
11997         surface.num_firsttriangle = firsttriangle;
11998         surface.num_vertices = numvertices;
11999         surface.num_firstvertex = firstvertex;
12000
12001         // now render it
12002         rsurface.texture = R_GetCurrentTexture(surface.texture);
12003         rsurface.uselightmaptexture = false;
12004         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12005 }
12006
12007 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)
12008 {
12009         static msurface_t surface;
12010         const msurface_t *surfacelist = &surface;
12011
12012         // fake enough texture and surface state to render this geometry
12013
12014         surface.texture = texture;
12015         surface.num_triangles = numtriangles;
12016         surface.num_firsttriangle = firsttriangle;
12017         surface.num_vertices = numvertices;
12018         surface.num_firstvertex = firstvertex;
12019
12020         // now render it
12021         rsurface.texture = R_GetCurrentTexture(surface.texture);
12022         rsurface.uselightmaptexture = false;
12023         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12024 }