]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
remove some unwanted debug prints
[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", "1", "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 }
3634
3635 #ifdef SUPPORTCG
3636 #include <Cg/cgGL.h>
3637 struct r_cg_permutation_s;
3638 typedef struct r_cg_permutation_s
3639 {
3640         /// hash lookup data
3641         struct r_cg_permutation_s *hashnext;
3642         unsigned int mode;
3643         unsigned int permutation;
3644
3645         /// indicates if we have tried compiling this permutation already
3646         qboolean compiled;
3647         /// 0 if compilation failed
3648         CGprogram vprogram;
3649         CGprogram fprogram;
3650         /// locations of detected parameters in programs, or NULL if not found
3651         CGparameter vp_EyePosition;
3652         CGparameter vp_FogPlane;
3653         CGparameter vp_LightDir;
3654         CGparameter vp_LightPosition;
3655         CGparameter vp_ModelToLight;
3656         CGparameter vp_TexMatrix;
3657         CGparameter vp_BackgroundTexMatrix;
3658         CGparameter vp_ModelViewProjectionMatrix;
3659         CGparameter vp_ModelViewMatrix;
3660
3661         CGparameter fp_Texture_First;
3662         CGparameter fp_Texture_Second;
3663         CGparameter fp_Texture_GammaRamps;
3664         CGparameter fp_Texture_Normal;
3665         CGparameter fp_Texture_Color;
3666         CGparameter fp_Texture_Gloss;
3667         CGparameter fp_Texture_Glow;
3668         CGparameter fp_Texture_SecondaryNormal;
3669         CGparameter fp_Texture_SecondaryColor;
3670         CGparameter fp_Texture_SecondaryGloss;
3671         CGparameter fp_Texture_SecondaryGlow;
3672         CGparameter fp_Texture_Pants;
3673         CGparameter fp_Texture_Shirt;
3674         CGparameter fp_Texture_FogMask;
3675         CGparameter fp_Texture_Lightmap;
3676         CGparameter fp_Texture_Deluxemap;
3677         CGparameter fp_Texture_Attenuation;
3678         CGparameter fp_Texture_Cube;
3679         CGparameter fp_Texture_Refraction;
3680         CGparameter fp_Texture_Reflection;
3681         CGparameter fp_Texture_ShadowMapRect;
3682         CGparameter fp_Texture_ShadowMapCube;
3683         CGparameter fp_Texture_ShadowMap2D;
3684         CGparameter fp_Texture_CubeProjection;
3685         CGparameter fp_Texture_ScreenDepth;
3686         CGparameter fp_Texture_ScreenNormalMap;
3687         CGparameter fp_Texture_ScreenDiffuse;
3688         CGparameter fp_Texture_ScreenSpecular;
3689         CGparameter fp_Alpha;
3690         CGparameter fp_BloomBlur_Parameters;
3691         CGparameter fp_ClientTime;
3692         CGparameter fp_Color_Ambient;
3693         CGparameter fp_Color_Diffuse;
3694         CGparameter fp_Color_Specular;
3695         CGparameter fp_Color_Glow;
3696         CGparameter fp_Color_Pants;
3697         CGparameter fp_Color_Shirt;
3698         CGparameter fp_DeferredColor_Ambient;
3699         CGparameter fp_DeferredColor_Diffuse;
3700         CGparameter fp_DeferredColor_Specular;
3701         CGparameter fp_DeferredMod_Diffuse;
3702         CGparameter fp_DeferredMod_Specular;
3703         CGparameter fp_DistortScaleRefractReflect;
3704         CGparameter fp_EyePosition;
3705         CGparameter fp_FogColor;
3706         CGparameter fp_FogHeightFade;
3707         CGparameter fp_FogPlane;
3708         CGparameter fp_FogPlaneViewDist;
3709         CGparameter fp_FogRangeRecip;
3710         CGparameter fp_LightColor;
3711         CGparameter fp_LightDir;
3712         CGparameter fp_LightPosition;
3713         CGparameter fp_OffsetMapping_Scale;
3714         CGparameter fp_PixelSize;
3715         CGparameter fp_ReflectColor;
3716         CGparameter fp_ReflectFactor;
3717         CGparameter fp_ReflectOffset;
3718         CGparameter fp_RefractColor;
3719         CGparameter fp_Saturation;
3720         CGparameter fp_ScreenCenterRefractReflect;
3721         CGparameter fp_ScreenScaleRefractReflect;
3722         CGparameter fp_ScreenToDepth;
3723         CGparameter fp_ShadowMap_Parameters;
3724         CGparameter fp_ShadowMap_TextureScale;
3725         CGparameter fp_SpecularPower;
3726         CGparameter fp_UserVec1;
3727         CGparameter fp_UserVec2;
3728         CGparameter fp_UserVec3;
3729         CGparameter fp_UserVec4;
3730         CGparameter fp_ViewTintColor;
3731         CGparameter fp_ViewToLight;
3732 }
3733 r_cg_permutation_t;
3734
3735 /// information about each possible shader permutation
3736 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3737 /// currently selected permutation
3738 r_cg_permutation_t *r_cg_permutation;
3739 /// storage for permutations linked in the hash table
3740 memexpandablearray_t r_cg_permutationarray;
3741
3742 #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));}}
3743
3744 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3745 {
3746         //unsigned int hashdepth = 0;
3747         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3748         r_cg_permutation_t *p;
3749         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3750         {
3751                 if (p->mode == mode && p->permutation == permutation)
3752                 {
3753                         //if (hashdepth > 10)
3754                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3755                         return p;
3756                 }
3757                 //hashdepth++;
3758         }
3759         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3760         p->mode = mode;
3761         p->permutation = permutation;
3762         p->hashnext = r_cg_permutationhash[mode][hashindex];
3763         r_cg_permutationhash[mode][hashindex] = p;
3764         //if (hashdepth > 10)
3765         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3766         return p;
3767 }
3768
3769 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3770 {
3771         char *shaderstring;
3772         if (!filename || !filename[0])
3773                 return NULL;
3774         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3775         if (shaderstring)
3776         {
3777                 if (printfromdisknotice)
3778                         Con_DPrintf("from disk %s... ", filename);
3779                 return shaderstring;
3780         }
3781         else if (!strcmp(filename, "cg/default.cg"))
3782         {
3783                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtincgshaderstring) + 1);
3784                 memcpy(shaderstring, builtincgshaderstring, strlen(builtincgshaderstring) + 1);
3785         }
3786         return shaderstring;
3787 }
3788
3789 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
3790 {
3791         int i;
3792         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
3793         int vertstrings_count = 0, vertstring_length = 0;
3794         int geomstrings_count = 0, geomstring_length = 0;
3795         int fragstrings_count = 0, fragstring_length = 0;
3796         char *t;
3797         char *vertexstring, *geometrystring, *fragmentstring;
3798         char *vertstring, *geomstring, *fragstring;
3799         const char *vertstrings_list[32+3];
3800         const char *geomstrings_list[32+3];
3801         const char *fragstrings_list[32+3];
3802         char permutationname[256];
3803         CGprofile vertexProfile;
3804         CGprofile fragmentProfile;
3805
3806         if (p->compiled)
3807                 return;
3808         p->compiled = true;
3809         p->vprogram = NULL;
3810         p->fprogram = NULL;
3811
3812         permutationname[0] = 0;
3813         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
3814         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
3815         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
3816
3817         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3818
3819         // the first pretext is which type of shader to compile as
3820         // (later these will all be bound together as a program object)
3821         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3822         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3823         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3824
3825         // the second pretext is the mode (for example a light source)
3826         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3827         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3828         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3829         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3830
3831         // now add all the permutation pretexts
3832         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3833         {
3834                 if (permutation & (1<<i))
3835                 {
3836                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3837                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3838                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3839                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3840                 }
3841                 else
3842                 {
3843                         // keep line numbers correct
3844                         vertstrings_list[vertstrings_count++] = "\n";
3845                         geomstrings_list[geomstrings_count++] = "\n";
3846                         fragstrings_list[fragstrings_count++] = "\n";
3847                 }
3848         }
3849
3850         // now append the shader text itself
3851         vertstrings_list[vertstrings_count++] = vertexstring;
3852         geomstrings_list[geomstrings_count++] = geometrystring;
3853         fragstrings_list[fragstrings_count++] = fragmentstring;
3854
3855         // if any sources were NULL, clear the respective list
3856         if (!vertexstring)
3857                 vertstrings_count = 0;
3858         if (!geometrystring)
3859                 geomstrings_count = 0;
3860         if (!fragmentstring)
3861                 fragstrings_count = 0;
3862
3863         vertstring_length = 0;
3864         for (i = 0;i < vertstrings_count;i++)
3865                 vertstring_length += strlen(vertstrings_list[i]);
3866         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
3867         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
3868                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
3869
3870         geomstring_length = 0;
3871         for (i = 0;i < geomstrings_count;i++)
3872                 geomstring_length += strlen(geomstrings_list[i]);
3873         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
3874         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
3875                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
3876
3877         fragstring_length = 0;
3878         for (i = 0;i < fragstrings_count;i++)
3879                 fragstring_length += strlen(fragstrings_list[i]);
3880         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
3881         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
3882                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
3883
3884         CHECKGLERROR
3885         CHECKCGERROR
3886         //vertexProfile = CG_PROFILE_ARBVP1;
3887         //fragmentProfile = CG_PROFILE_ARBFP1;
3888         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
3889         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
3890         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
3891         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
3892         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
3893         CHECKGLERROR
3894
3895         // compile the vertex program
3896         if (vertstring[0] && (p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, CG_PROFILE_ARBVP1, NULL, NULL)))
3897         {
3898                 CHECKCGERROR
3899                 cgCompileProgram(p->vprogram);CHECKCGERROR
3900                 if (!cgIsProgramCompiled(p->vprogram))
3901                 {
3902                         CHECKCGERROR
3903                         cgDestroyProgram(p->vprogram);CHECKCGERROR
3904                         p->vprogram = 0;
3905                 }
3906                 else
3907                 {
3908                         cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
3909                         cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
3910                         // look up all the uniform variable names we care about, so we don't
3911                         // have to look them up every time we set them
3912                         CHECKCGERROR
3913                         p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
3914                         p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
3915                         p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
3916                         p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
3917                         p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
3918                         p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
3919                         p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
3920                         p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
3921                         p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
3922                         CHECKCGERROR
3923                 }
3924         }
3925
3926         // compile the fragment program
3927         if (fragstring[0] && (p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, CG_PROFILE_ARBFP1, NULL, NULL)))
3928         {
3929                 cgCompileProgram(p->fprogram);CHECKCGERROR
3930                 if (!cgIsProgramCompiled(p->fprogram))
3931                 {
3932                         CHECKCGERROR
3933                         cgDestroyProgram(p->fprogram);CHECKCGERROR
3934                         p->fprogram = 0;
3935                 }
3936                 else
3937                 {
3938                         cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
3939                         cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
3940                         CHECKCGERROR
3941                         p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
3942                         p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
3943                         p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
3944                         p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
3945                         p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
3946                         p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
3947                         p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
3948                         p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
3949                         p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
3950                         p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
3951                         p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
3952                         p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
3953                         p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
3954                         p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
3955                         p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
3956                         p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
3957                         p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
3958                         p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
3959                         p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
3960                         p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
3961                         p->fp_Texture_ShadowMapRect      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
3962                         p->fp_Texture_ShadowMapCube      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
3963                         p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
3964                         p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
3965                         p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
3966                         p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
3967                         p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
3968                         p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
3969                         p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
3970                         p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
3971                         p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
3972                         p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
3973                         p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
3974                         p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
3975                         p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
3976                         p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
3977                         p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
3978                         p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
3979                         p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
3980                         p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
3981                         p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
3982                         p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
3983                         p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
3984                         p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
3985                         p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
3986                         p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
3987                         p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
3988                         p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
3989                         p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
3990                         p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
3991                         p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
3992                         p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
3993                         p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
3994                         p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
3995                         p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
3996                         p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
3997                         p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
3998                         p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
3999                         p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4000                         p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4001                         p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4002                         p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4003                         p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4004                         p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4005                         p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4006                         p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4007                         p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4008                         p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4009                         p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4010                         p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4011                         p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4012                         CHECKCGERROR
4013                 }
4014         }
4015
4016         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4017                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4018         else
4019                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4020
4021         // free the strings
4022         if (vertstring)
4023                 Mem_Free(vertstring);
4024         if (geomstring)
4025                 Mem_Free(geomstring);
4026         if (fragstring)
4027                 Mem_Free(fragstring);
4028         if (vertexstring)
4029                 Mem_Free(vertexstring);
4030         if (geometrystring)
4031                 Mem_Free(geometrystring);
4032         if (fragmentstring)
4033                 Mem_Free(fragmentstring);
4034 }
4035
4036 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4037 {
4038         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4039         CHECKGLERROR
4040         CHECKCGERROR
4041         if (r_cg_permutation != perm)
4042         {
4043                 r_cg_permutation = perm;
4044                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4045                 {
4046                         if (!r_cg_permutation->compiled)
4047                                 R_CG_CompilePermutation(perm, mode, permutation);
4048                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4049                         {
4050                                 // remove features until we find a valid permutation
4051                                 int i;
4052                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4053                                 {
4054                                         // reduce i more quickly whenever it would not remove any bits
4055                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4056                                         if (!(permutation & j))
4057                                                 continue;
4058                                         permutation -= j;
4059                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4060                                         if (!r_cg_permutation->compiled)
4061                                                 R_CG_CompilePermutation(perm, mode, permutation);
4062                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4063                                                 break;
4064                                 }
4065                                 if (i >= SHADERPERMUTATION_COUNT)
4066                                 {
4067                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4068                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4069                                         return; // no bit left to clear, entire mode is broken
4070                                 }
4071                         }
4072                 }
4073                 CHECKGLERROR
4074                 CHECKCGERROR
4075                 if (r_cg_permutation->vprogram)
4076                 {
4077                         //cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4078                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4079                         //cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4080                 }
4081                 else
4082                 {
4083                         //cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4084                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4085                 }
4086                 if (r_cg_permutation->fprogram)
4087                 {
4088                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4089                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4090                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4091                 }
4092                 else
4093                 {
4094                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4095                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4096                 }
4097         }
4098         CHECKCGERROR
4099         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4100 }
4101
4102 void CG_BindTexture(CGparameter param, int texnum)
4103 {
4104         cgGLSetTextureParameter(param, texnum);
4105         cgGLEnableTextureParameter(param);
4106 }
4107 #endif
4108
4109 void R_GLSL_Restart_f(void)
4110 {
4111         unsigned int i, limit;
4112         switch(vid.renderpath)
4113         {
4114         case RENDERPATH_GL20:
4115                 {
4116                         r_glsl_permutation_t *p;
4117                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4118                         for (i = 0;i < limit;i++)
4119                         {
4120                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4121                                 {
4122                                         GL_Backend_FreeProgram(p->program);
4123                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4124                                 }
4125                         }
4126                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4127                 }
4128                 break;
4129         case RENDERPATH_CGGL:
4130 #ifdef SUPPORTCG
4131                 {
4132                         r_cg_permutation_t *p;
4133                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4134                         for (i = 0;i < limit;i++)
4135                         {
4136                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4137                                 {
4138                                         if (p->vprogram)
4139                                                 cgDestroyProgram(p->vprogram);
4140                                         if (p->fprogram)
4141                                                 cgDestroyProgram(p->fprogram);
4142                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4143                                 }
4144                         }
4145                 }
4146                 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4147                 break;
4148 #endif
4149         case RENDERPATH_GL13:
4150         case RENDERPATH_GL11:
4151                 break;
4152         }
4153 }
4154
4155 void R_GLSL_DumpShader_f(void)
4156 {
4157         int i;
4158         qfile_t *file;
4159
4160         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4161         if (file)
4162         {
4163                 FS_Print(file, "/* The engine may define the following macros:\n");
4164                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4165                 for (i = 0;i < SHADERMODE_COUNT;i++)
4166                         FS_Print(file, glslshadermodeinfo[i].pretext);
4167                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4168                         FS_Print(file, shaderpermutationinfo[i].pretext);
4169                 FS_Print(file, "*/\n");
4170                 FS_Print(file, builtinshaderstring);
4171                 FS_Close(file);
4172                 Con_Printf("glsl/default.glsl written\n");
4173         }
4174         else
4175                 Con_Printf("failed to write to glsl/default.glsl\n");
4176
4177 #ifdef SUPPORTCG
4178         file = FS_OpenRealFile("cg/default.cg", "w", false);
4179         if (file)
4180         {
4181                 FS_Print(file, "/* The engine may define the following macros:\n");
4182                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4183                 for (i = 0;i < SHADERMODE_COUNT;i++)
4184                         FS_Print(file, cgshadermodeinfo[i].pretext);
4185                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4186                         FS_Print(file, shaderpermutationinfo[i].pretext);
4187                 FS_Print(file, "*/\n");
4188                 FS_Print(file, builtincgshaderstring);
4189                 FS_Close(file);
4190                 Con_Printf("cg/default.cg written\n");
4191         }
4192         else
4193                 Con_Printf("failed to write to cg/default.cg\n");
4194 #endif
4195 }
4196
4197 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4198 {
4199         if (!second)
4200                 texturemode = GL_MODULATE;
4201         switch (vid.renderpath)
4202         {
4203         case RENDERPATH_GL20:
4204                 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))));
4205                 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
4206                 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, second);
4207                 break;
4208         case RENDERPATH_CGGL:
4209 #ifdef SUPPORTCG
4210                 CHECKCGERROR
4211                 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))));
4212                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4213                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4214 #endif
4215                 break;
4216         case RENDERPATH_GL13:
4217                 R_Mesh_TexBind(0, first );
4218                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4219                 R_Mesh_TexBind(1, second);
4220                 if (second)
4221                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4222                 break;
4223         case RENDERPATH_GL11:
4224                 R_Mesh_TexBind(0, first );
4225                 break;
4226         }
4227 }
4228
4229 void R_SetupShader_DepthOrShadow(void)
4230 {
4231         switch (vid.renderpath)
4232         {
4233         case RENDERPATH_GL20:
4234                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4235                 break;
4236         case RENDERPATH_CGGL:
4237 #ifdef SUPPORTCG
4238                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4239 #endif
4240                 break;
4241         case RENDERPATH_GL13:
4242                 R_Mesh_TexBind(0, 0);
4243                 R_Mesh_TexBind(1, 0);
4244                 break;
4245         case RENDERPATH_GL11:
4246                 R_Mesh_TexBind(0, 0);
4247                 break;
4248         }
4249 }
4250
4251 void R_SetupShader_ShowDepth(void)
4252 {
4253         switch (vid.renderpath)
4254         {
4255         case RENDERPATH_GL20:
4256                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4257                 break;
4258         case RENDERPATH_CGGL:
4259 #ifdef SUPPORTCG
4260                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4261 #endif
4262                 break;
4263         case RENDERPATH_GL13:
4264                 break;
4265         case RENDERPATH_GL11:
4266                 break;
4267         }
4268 }
4269
4270 extern qboolean r_shadow_usingdeferredprepass;
4271 extern cvar_t r_shadow_deferred_8bitrange;
4272 extern rtexture_t *r_shadow_attenuationgradienttexture;
4273 extern rtexture_t *r_shadow_attenuation2dtexture;
4274 extern rtexture_t *r_shadow_attenuation3dtexture;
4275 extern qboolean r_shadow_usingshadowmaprect;
4276 extern qboolean r_shadow_usingshadowmapcube;
4277 extern qboolean r_shadow_usingshadowmap2d;
4278 extern float r_shadow_shadowmap_texturescale[2];
4279 extern float r_shadow_shadowmap_parameters[4];
4280 extern qboolean r_shadow_shadowmapvsdct;
4281 extern qboolean r_shadow_shadowmapsampler;
4282 extern int r_shadow_shadowmappcf;
4283 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4284 extern rtexture_t *r_shadow_shadowmap2dtexture;
4285 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4286 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4287 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4288 extern int r_shadow_prepass_width;
4289 extern int r_shadow_prepass_height;
4290 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4291 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4292 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4293 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4294 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
4295 {
4296         // select a permutation of the lighting shader appropriate to this
4297         // combination of texture, entity, light source, and fogging, only use the
4298         // minimum features necessary to avoid wasting rendering time in the
4299         // fragment shader on features that are not being used
4300         unsigned int permutation = 0;
4301         unsigned int mode = 0;
4302         float m16f[16];
4303         // TODO: implement geometry-shader based shadow volumes someday
4304         if (r_glsl_offsetmapping.integer)
4305         {
4306                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4307                 if (r_glsl_offsetmapping_reliefmapping.integer)
4308                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4309         }
4310         if (rsurfacepass == RSURFPASS_BACKGROUND)
4311         {
4312                 // distorted background
4313                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4314                         mode = SHADERMODE_WATER;
4315                 else
4316                         mode = SHADERMODE_REFRACTION;
4317         }
4318         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4319         {
4320                 // normalmap (deferred prepass), may use alpha test on diffuse
4321                 mode = SHADERMODE_DEFERREDGEOMETRY;
4322                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4323                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4324                 if (r_glsl_offsetmapping.integer)
4325                 {
4326                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4327                         if (r_glsl_offsetmapping_reliefmapping.integer)
4328                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4329                 }
4330         }
4331         else if (rsurfacepass == RSURFPASS_RTLIGHT)
4332         {
4333                 // light source
4334                 mode = SHADERMODE_LIGHTSOURCE;
4335                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4336                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4337                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4338                         permutation |= SHADERPERMUTATION_CUBEFILTER;
4339                 if (diffusescale > 0)
4340                         permutation |= SHADERPERMUTATION_DIFFUSE;
4341                 if (specularscale > 0)
4342                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4343                 if (r_refdef.fogenabled)
4344                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4345                 if (rsurface.texture->colormapping)
4346                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4347                 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4348                 {
4349                         if (r_shadow_usingshadowmaprect)
4350                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4351                         if (r_shadow_usingshadowmap2d)
4352                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4353                         if (r_shadow_usingshadowmapcube)
4354                                 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4355                         else if(r_shadow_shadowmapvsdct)
4356                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4357
4358                         if (r_shadow_shadowmapsampler)
4359                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4360                         if (r_shadow_shadowmappcf > 1)
4361                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4362                         else if (r_shadow_shadowmappcf)
4363                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4364                 }
4365         }
4366         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4367         {
4368                 // unshaded geometry (fullbright or ambient model lighting)
4369                 mode = SHADERMODE_FLATCOLOR;
4370                 ambientscale = diffusescale = specularscale = 0;
4371                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4372                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4373                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4374                         permutation |= SHADERPERMUTATION_GLOW;
4375                 if (r_refdef.fogenabled)
4376                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4377                 if (rsurface.texture->colormapping)
4378                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4379                 if (r_glsl_offsetmapping.integer)
4380                 {
4381                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4382                         if (r_glsl_offsetmapping_reliefmapping.integer)
4383                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4384                 }
4385                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4386                         permutation |= SHADERPERMUTATION_REFLECTION;
4387         }
4388         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4389         {
4390                 // directional model lighting
4391                 mode = SHADERMODE_LIGHTDIRECTION;
4392                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4393                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4394                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4395                         permutation |= SHADERPERMUTATION_GLOW;
4396                 permutation |= SHADERPERMUTATION_DIFFUSE;
4397                 if (specularscale > 0)
4398                         permutation |= SHADERPERMUTATION_SPECULAR;
4399                 if (r_refdef.fogenabled)
4400                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4401                 if (rsurface.texture->colormapping)
4402                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4403                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4404                         permutation |= SHADERPERMUTATION_REFLECTION;
4405                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4406                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4407         }
4408         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
4409         {
4410                 // ambient model lighting
4411                 mode = SHADERMODE_LIGHTDIRECTION;
4412                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4413                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4414                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4415                         permutation |= SHADERPERMUTATION_GLOW;
4416                 if (r_refdef.fogenabled)
4417                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4418                 if (rsurface.texture->colormapping)
4419                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4420                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4421                         permutation |= SHADERPERMUTATION_REFLECTION;
4422                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4423                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4424         }
4425         else
4426         {
4427                 // lightmapped wall
4428                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
4429                 {
4430                         // deluxemapping (light direction texture)
4431                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
4432                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
4433                         else
4434                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4435                         permutation |= SHADERPERMUTATION_DIFFUSE;
4436                         if (specularscale > 0)
4437                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4438                 }
4439                 else if (r_glsl_deluxemapping.integer >= 2)
4440                 {
4441                         // fake deluxemapping (uniform light direction in tangentspace)
4442                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4443                         permutation |= SHADERPERMUTATION_DIFFUSE;
4444                         if (specularscale > 0)
4445                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4446                 }
4447                 else if (rsurface.uselightmaptexture)
4448                 {
4449                         // ordinary lightmapping (q1bsp, q3bsp)
4450                         mode = SHADERMODE_LIGHTMAP;
4451                 }
4452                 else
4453                 {
4454                         // ordinary vertex coloring (q3bsp)
4455                         mode = SHADERMODE_VERTEXCOLOR;
4456                 }
4457                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4458                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4459                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4460                         permutation |= SHADERPERMUTATION_GLOW;
4461                 if (r_refdef.fogenabled)
4462                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4463                 if (rsurface.texture->colormapping)
4464                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4465                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4466                         permutation |= SHADERPERMUTATION_REFLECTION;
4467                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4468                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4469         }
4470         if(permutation & SHADERPERMUTATION_SPECULAR)
4471                 if(r_shadow_glossexact.integer)
4472                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4473         if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) && r_shadow_usingdeferredprepass)
4474                 permutation |= SHADERPERMUTATION_ALPHAKILL;
4475         switch(vid.renderpath)
4476         {
4477         case RENDERPATH_GL20:
4478                 R_SetupShader_SetPermutationGLSL(mode, permutation);
4479                 if (mode == SHADERMODE_LIGHTSOURCE)
4480                 {
4481                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
4482                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
4483                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
4484                         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);
4485                         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);
4486                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, specularscale, specularscale, specularscale);
4487         
4488                         // additive passes are only darkened by fog, not tinted
4489                         if (r_glsl_permutation->loc_FogColor >= 0)
4490                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4491                         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]);
4492                         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]);
4493                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4494                 }
4495                 else
4496                 {
4497                         if (mode == SHADERMODE_FLATCOLOR)
4498                         {
4499                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
4500                         }
4501                         else if (mode == SHADERMODE_LIGHTDIRECTION)
4502                         {
4503                                 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]);
4504                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity, r_refdef.lightmapintensity, r_refdef.lightmapintensity);
4505                                 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);
4506                                 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);
4507                                 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);
4508                                 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]);
4509                                 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]);
4510                         }
4511                         else
4512                         {
4513                                 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]);
4514                                 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]);
4515                                 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);
4516                                 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);
4517                                 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);
4518                         }
4519                         // additive passes are only darkened by fog, not tinted
4520                         if (r_glsl_permutation->loc_FogColor >= 0)
4521                         {
4522                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4523                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4524                                 else
4525                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4526                         }
4527                         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);
4528                         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]);
4529                         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]);
4530                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
4531                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
4532                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
4533                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
4534                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4535                 }
4536                 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
4537                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
4538                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
4539                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
4540                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
4541                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
4542                 if (r_glsl_permutation->loc_Color_Pants >= 0)
4543                 {
4544                         if (rsurface.texture->pantstexture)
4545                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4546                         else
4547                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
4548                 }
4549                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
4550                 {
4551                         if (rsurface.texture->shirttexture)
4552                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4553                         else
4554                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
4555                 }
4556                 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]);
4557                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
4558                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
4559                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
4560                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
4561                 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]);
4562
4563         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
4564         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
4565         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
4566                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
4567                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
4568                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
4569                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
4570                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
4571                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
4572                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
4573                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
4574                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
4575                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
4576                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
4577                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_white                                     );
4578                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_blanknormalmap                            );
4579                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
4580                 if (r_glsl_permutation->loc_Texture_Refraction      >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , r_texture_white                                     );
4581                 if (r_glsl_permutation->loc_Texture_Reflection      >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , r_texture_white                                     );
4582                 if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
4583                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
4584                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
4585                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
4586                 if (rsurface.rtlight)
4587                 {
4588                         if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
4589                         if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT     , r_shadow_shadowmaprectangletexture                  );
4590                         if (r_shadow_usingshadowmapcube)
4591                                 if (r_glsl_permutation->loc_Texture_ShadowMapCube   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE     , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
4592                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D       , r_shadow_shadowmap2dtexture                         );
4593                         if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
4594                 }
4595                 CHECKGLERROR
4596                 break;
4597         case RENDERPATH_CGGL:
4598 #ifdef SUPPORTCG
4599                 R_SetupShader_SetPermutationCG(mode, permutation);
4600                 if (mode == SHADERMODE_LIGHTSOURCE)
4601                 {
4602                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
4603                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4604                 }
4605                 else
4606                 {
4607                         if (mode == SHADERMODE_LIGHTDIRECTION)
4608                         {
4609                                 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
4610                         }
4611                 }
4612                 if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelviewprojection16f);CHECKCGERROR
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_ModelViewMatrix           >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix          , 1, false, gl_modelview16f);
4801                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
4802                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
4803                 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);
4804                 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);
4805                 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);
4806                 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]);
4807                 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]);
4808                 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));
4809                 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]);
4810
4811                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
4812                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
4813                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
4814                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
4815                 if (r_glsl_permutation->loc_Texture_ShadowMapRect     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT      , r_shadow_shadowmaprectangletexture                  );
4816                 if (r_shadow_usingshadowmapcube)
4817                         if (r_glsl_permutation->loc_Texture_ShadowMapCube     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE      , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
4818                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
4819                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
4820                 break;
4821         case RENDERPATH_CGGL:
4822 #ifdef SUPPORTCG
4823                 R_SetupShader_SetPermutationCG(mode, permutation);
4824                 if (r_cg_permutation->vp_ModelViewMatrix          ) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelviewprojection16f);CHECKCGERROR
4825                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
4826                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
4827                 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
4828                 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
4829                 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
4830                 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
4831                 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
4832                 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
4833                 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
4834
4835                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
4836                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
4837                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
4838                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
4839                 if (r_cg_permutation->fp_Texture_ShadowMapRect    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
4840                 if (r_shadow_usingshadowmapcube)
4841                         if (r_cg_permutation->fp_Texture_ShadowMapCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
4842                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
4843                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
4844 #endif
4845                 break;
4846         case RENDERPATH_GL13:
4847         case RENDERPATH_GL11:
4848                 break;
4849         }
4850 }
4851
4852 #define SKINFRAME_HASH 1024
4853
4854 typedef struct
4855 {
4856         int loadsequence; // incremented each level change
4857         memexpandablearray_t array;
4858         skinframe_t *hash[SKINFRAME_HASH];
4859 }
4860 r_skinframe_t;
4861 r_skinframe_t r_skinframe;
4862
4863 void R_SkinFrame_PrepareForPurge(void)
4864 {
4865         r_skinframe.loadsequence++;
4866         // wrap it without hitting zero
4867         if (r_skinframe.loadsequence >= 200)
4868                 r_skinframe.loadsequence = 1;
4869 }
4870
4871 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
4872 {
4873         if (!skinframe)
4874                 return;
4875         // mark the skinframe as used for the purging code
4876         skinframe->loadsequence = r_skinframe.loadsequence;
4877 }
4878
4879 void R_SkinFrame_Purge(void)
4880 {
4881         int i;
4882         skinframe_t *s;
4883         for (i = 0;i < SKINFRAME_HASH;i++)
4884         {
4885                 for (s = r_skinframe.hash[i];s;s = s->next)
4886                 {
4887                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
4888                         {
4889                                 if (s->merged == s->base)
4890                                         s->merged = NULL;
4891                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
4892                                 R_PurgeTexture(s->stain );s->stain  = NULL;
4893                                 R_PurgeTexture(s->merged);s->merged = NULL;
4894                                 R_PurgeTexture(s->base  );s->base   = NULL;
4895                                 R_PurgeTexture(s->pants );s->pants  = NULL;
4896                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
4897                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
4898                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
4899                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
4900                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
4901                                 s->loadsequence = 0;
4902                         }
4903                 }
4904         }
4905 }
4906
4907 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
4908         skinframe_t *item;
4909         char basename[MAX_QPATH];
4910
4911         Image_StripImageExtension(name, basename, sizeof(basename));
4912
4913         if( last == NULL ) {
4914                 int hashindex;
4915                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
4916                 item = r_skinframe.hash[hashindex];
4917         } else {
4918                 item = last->next;
4919         }
4920
4921         // linearly search through the hash bucket
4922         for( ; item ; item = item->next ) {
4923                 if( !strcmp( item->basename, basename ) ) {
4924                         return item;
4925                 }
4926         }
4927         return NULL;
4928 }
4929
4930 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
4931 {
4932         skinframe_t *item;
4933         int hashindex;
4934         char basename[MAX_QPATH];
4935
4936         Image_StripImageExtension(name, basename, sizeof(basename));
4937
4938         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
4939         for (item = r_skinframe.hash[hashindex];item;item = item->next)
4940                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
4941                         break;
4942
4943         if (!item) {
4944                 rtexture_t *dyntexture;
4945                 // check whether its a dynamic texture
4946                 dyntexture = CL_GetDynTexture( basename );
4947                 if (!add && !dyntexture)
4948                         return NULL;
4949                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
4950                 memset(item, 0, sizeof(*item));
4951                 strlcpy(item->basename, basename, sizeof(item->basename));
4952                 item->base = dyntexture; // either NULL or dyntexture handle
4953                 item->textureflags = textureflags;
4954                 item->comparewidth = comparewidth;
4955                 item->compareheight = compareheight;
4956                 item->comparecrc = comparecrc;
4957                 item->next = r_skinframe.hash[hashindex];
4958                 r_skinframe.hash[hashindex] = item;
4959         }
4960         else if( item->base == NULL )
4961         {
4962                 rtexture_t *dyntexture;
4963                 // check whether its a dynamic texture
4964                 // 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]
4965                 dyntexture = CL_GetDynTexture( basename );
4966                 item->base = dyntexture; // either NULL or dyntexture handle
4967         }
4968
4969         R_SkinFrame_MarkUsed(item);
4970         return item;
4971 }
4972
4973 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
4974         { \
4975                 unsigned long long avgcolor[5], wsum; \
4976                 int pix, comp, w; \
4977                 avgcolor[0] = 0; \
4978                 avgcolor[1] = 0; \
4979                 avgcolor[2] = 0; \
4980                 avgcolor[3] = 0; \
4981                 avgcolor[4] = 0; \
4982                 wsum = 0; \
4983                 for(pix = 0; pix < cnt; ++pix) \
4984                 { \
4985                         w = 0; \
4986                         for(comp = 0; comp < 3; ++comp) \
4987                                 w += getpixel; \
4988                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
4989                         { \
4990                                 ++wsum; \
4991                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
4992                                 w = getpixel; \
4993                                 for(comp = 0; comp < 3; ++comp) \
4994                                         avgcolor[comp] += getpixel * w; \
4995                                 avgcolor[3] += w; \
4996                         } \
4997                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
4998                         avgcolor[4] += getpixel; \
4999                 } \
5000                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5001                         avgcolor[3] = 1; \
5002                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5003                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5004                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5005                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5006         }
5007
5008 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5009 {
5010         int j;
5011         unsigned char *pixels;
5012         unsigned char *bumppixels;
5013         unsigned char *basepixels = NULL;
5014         int basepixels_width = 0;
5015         int basepixels_height = 0;
5016         skinframe_t *skinframe;
5017         rtexture_t *ddsbase = NULL;
5018         qboolean ddshasalpha = false;
5019         float ddsavgcolor[4];
5020         char basename[MAX_QPATH];
5021
5022         if (cls.state == ca_dedicated)
5023                 return NULL;
5024
5025         // return an existing skinframe if already loaded
5026         // if loading of the first image fails, don't make a new skinframe as it
5027         // would cause all future lookups of this to be missing
5028         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5029         if (skinframe && skinframe->base)
5030                 return skinframe;
5031
5032         Image_StripImageExtension(name, basename, sizeof(basename));
5033
5034         // check for DDS texture file first
5035         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor)))
5036         {
5037                 basepixels = loadimagepixelsbgra(name, complain, true);
5038                 if (basepixels == NULL)
5039                         return NULL;
5040         }
5041
5042         if (developer_loading.integer)
5043                 Con_Printf("loading skin \"%s\"\n", name);
5044
5045         // we've got some pixels to store, so really allocate this new texture now
5046         if (!skinframe)
5047                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5048         skinframe->stain = NULL;
5049         skinframe->merged = NULL;
5050         skinframe->base = NULL;
5051         skinframe->pants = NULL;
5052         skinframe->shirt = NULL;
5053         skinframe->nmap = NULL;
5054         skinframe->gloss = NULL;
5055         skinframe->glow = NULL;
5056         skinframe->fog = NULL;
5057         skinframe->hasalpha = false;
5058
5059         if (ddsbase)
5060         {
5061                 skinframe->base = ddsbase;
5062                 skinframe->hasalpha = ddshasalpha;
5063                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5064                 if (r_loadfog && skinframe->hasalpha)
5065                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5066                 //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]);
5067         }
5068         else
5069         {
5070                 basepixels_width = image_width;
5071                 basepixels_height = image_height;
5072                 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);
5073                 if (textureflags & TEXF_ALPHA)
5074                 {
5075                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5076                         {
5077                                 if (basepixels[j] < 255)
5078                                 {
5079                                         skinframe->hasalpha = true;
5080                                         break;
5081                                 }
5082                         }
5083                         if (r_loadfog && skinframe->hasalpha)
5084                         {
5085                                 // has transparent pixels
5086                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5087                                 for (j = 0;j < image_width * image_height * 4;j += 4)
5088                                 {
5089                                         pixels[j+0] = 255;
5090                                         pixels[j+1] = 255;
5091                                         pixels[j+2] = 255;
5092                                         pixels[j+3] = basepixels[j+3];
5093                                 }
5094                                 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);
5095                                 Mem_Free(pixels);
5096                         }
5097                 }
5098                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5099                 //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]);
5100                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5101                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true);
5102                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
5103                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true);
5104         }
5105
5106         if (r_loaddds)
5107         {
5108                 if (r_loadnormalmap)
5109                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5110                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL);
5111                 if (r_loadgloss)
5112                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL);
5113                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL);
5114                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL);
5115         }
5116
5117         // _norm is the name used by tenebrae and has been adopted as standard
5118         if (r_loadnormalmap && skinframe->nmap == NULL)
5119         {
5120                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
5121                 {
5122                         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);
5123                         Mem_Free(pixels);
5124                         pixels = NULL;
5125                 }
5126                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
5127                 {
5128                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5129                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5130                         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);
5131                         Mem_Free(pixels);
5132                         Mem_Free(bumppixels);
5133                 }
5134                 else if (r_shadow_bumpscale_basetexture.value > 0)
5135                 {
5136                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5137                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5138                         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);
5139                         Mem_Free(pixels);
5140                 }
5141                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
5142                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true);
5143         }
5144
5145         // _luma is supported only for tenebrae compatibility
5146         // _glow is the preferred name
5147         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false))))
5148         {
5149                 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);
5150                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
5151                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true);
5152                 Mem_Free(pixels);pixels = NULL;
5153         }
5154
5155         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false)))
5156         {
5157                 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);
5158                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
5159                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true);
5160                 Mem_Free(pixels);
5161                 pixels = NULL;
5162         }
5163
5164         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false)))
5165         {
5166                 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);
5167                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
5168                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true);
5169                 Mem_Free(pixels);
5170                 pixels = NULL;
5171         }
5172
5173         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false)))
5174         {
5175                 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);
5176                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
5177                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true);
5178                 Mem_Free(pixels);
5179                 pixels = NULL;
5180         }
5181
5182         if (basepixels)
5183                 Mem_Free(basepixels);
5184
5185         return skinframe;
5186 }
5187
5188 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
5189 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
5190 {
5191         int i;
5192         unsigned char *temp1, *temp2;
5193         skinframe_t *skinframe;
5194
5195         if (cls.state == ca_dedicated)
5196                 return NULL;
5197
5198         // if already loaded just return it, otherwise make a new skinframe
5199         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
5200         if (skinframe && skinframe->base)
5201                 return skinframe;
5202
5203         skinframe->stain = NULL;
5204         skinframe->merged = NULL;
5205         skinframe->base = NULL;
5206         skinframe->pants = NULL;
5207         skinframe->shirt = NULL;
5208         skinframe->nmap = NULL;
5209         skinframe->gloss = NULL;
5210         skinframe->glow = NULL;
5211         skinframe->fog = NULL;
5212         skinframe->hasalpha = false;
5213
5214         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5215         if (!skindata)
5216                 return NULL;
5217
5218         if (developer_loading.integer)
5219                 Con_Printf("loading 32bit skin \"%s\"\n", name);
5220
5221         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
5222         {
5223                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5224                 temp2 = temp1 + width * height * 4;
5225                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5226                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5227                 Mem_Free(temp1);
5228         }
5229         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5230         if (textureflags & TEXF_ALPHA)
5231         {
5232                 for (i = 3;i < width * height * 4;i += 4)
5233                 {
5234                         if (skindata[i] < 255)
5235                         {
5236                                 skinframe->hasalpha = true;
5237                                 break;
5238                         }
5239                 }
5240                 if (r_loadfog && skinframe->hasalpha)
5241                 {
5242                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
5243                         memcpy(fogpixels, skindata, width * height * 4);
5244                         for (i = 0;i < width * height * 4;i += 4)
5245                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
5246                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5247                         Mem_Free(fogpixels);
5248                 }
5249         }
5250
5251         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
5252         //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]);
5253
5254         return skinframe;
5255 }
5256
5257 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
5258 {
5259         int i;
5260         int featuresmask;
5261         skinframe_t *skinframe;
5262
5263         if (cls.state == ca_dedicated)
5264                 return NULL;
5265
5266         // if already loaded just return it, otherwise make a new skinframe
5267         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5268         if (skinframe && skinframe->base)
5269                 return skinframe;
5270
5271         skinframe->stain = NULL;
5272         skinframe->merged = NULL;
5273         skinframe->base = NULL;
5274         skinframe->pants = NULL;
5275         skinframe->shirt = NULL;
5276         skinframe->nmap = NULL;
5277         skinframe->gloss = NULL;
5278         skinframe->glow = NULL;
5279         skinframe->fog = NULL;
5280         skinframe->hasalpha = false;
5281
5282         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5283         if (!skindata)
5284                 return NULL;
5285
5286         if (developer_loading.integer)
5287                 Con_Printf("loading quake skin \"%s\"\n", name);
5288
5289         // 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)
5290         skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
5291         memcpy(skinframe->qpixels, skindata, width*height);
5292         skinframe->qwidth = width;
5293         skinframe->qheight = height;
5294
5295         featuresmask = 0;
5296         for (i = 0;i < width * height;i++)
5297                 featuresmask |= palette_featureflags[skindata[i]];
5298
5299         skinframe->hasalpha = false;
5300         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
5301         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
5302         skinframe->qgeneratemerged = true;
5303         skinframe->qgeneratebase = skinframe->qhascolormapping;
5304         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
5305
5306         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
5307         //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]);
5308
5309         return skinframe;
5310 }
5311
5312 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
5313 {
5314         int width;
5315         int height;
5316         unsigned char *skindata;
5317
5318         if (!skinframe->qpixels)
5319                 return;
5320
5321         if (!skinframe->qhascolormapping)
5322                 colormapped = false;
5323
5324         if (colormapped)
5325         {
5326                 if (!skinframe->qgeneratebase)
5327                         return;
5328         }
5329         else
5330         {
5331                 if (!skinframe->qgeneratemerged)
5332                         return;
5333         }
5334
5335         width = skinframe->qwidth;
5336         height = skinframe->qheight;
5337         skindata = skinframe->qpixels;
5338
5339         if (skinframe->qgeneratenmap)
5340         {
5341                 unsigned char *temp1, *temp2;
5342                 skinframe->qgeneratenmap = false;
5343                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5344                 temp2 = temp1 + width * height * 4;
5345                 // use either a custom palette or the quake palette
5346                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
5347                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5348                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5349                 Mem_Free(temp1);
5350         }
5351
5352         if (skinframe->qgenerateglow)
5353         {
5354                 skinframe->qgenerateglow = false;
5355                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
5356         }
5357
5358         if (colormapped)
5359         {
5360                 skinframe->qgeneratebase = false;
5361                 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);
5362                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
5363                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
5364         }
5365         else
5366         {
5367                 skinframe->qgeneratemerged = false;
5368                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
5369         }
5370
5371         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
5372         {
5373                 Mem_Free(skinframe->qpixels);
5374                 skinframe->qpixels = NULL;
5375         }
5376 }
5377
5378 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)
5379 {
5380         int i;
5381         skinframe_t *skinframe;
5382
5383         if (cls.state == ca_dedicated)
5384                 return NULL;
5385
5386         // if already loaded just return it, otherwise make a new skinframe
5387         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5388         if (skinframe && skinframe->base)
5389                 return skinframe;
5390
5391         skinframe->stain = NULL;
5392         skinframe->merged = NULL;
5393         skinframe->base = NULL;
5394         skinframe->pants = NULL;
5395         skinframe->shirt = NULL;
5396         skinframe->nmap = NULL;
5397         skinframe->gloss = NULL;
5398         skinframe->glow = NULL;
5399         skinframe->fog = NULL;
5400         skinframe->hasalpha = false;
5401
5402         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5403         if (!skindata)
5404                 return NULL;
5405
5406         if (developer_loading.integer)
5407                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
5408
5409         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
5410         if (textureflags & TEXF_ALPHA)
5411         {
5412                 for (i = 0;i < width * height;i++)
5413                 {
5414                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
5415                         {
5416                                 skinframe->hasalpha = true;
5417                                 break;
5418                         }
5419                 }
5420                 if (r_loadfog && skinframe->hasalpha)
5421                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
5422         }
5423
5424         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
5425         //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]);
5426
5427         return skinframe;
5428 }
5429
5430 skinframe_t *R_SkinFrame_LoadMissing(void)
5431 {
5432         skinframe_t *skinframe;
5433
5434         if (cls.state == ca_dedicated)
5435                 return NULL;
5436
5437         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
5438         skinframe->stain = NULL;
5439         skinframe->merged = NULL;
5440         skinframe->base = NULL;
5441         skinframe->pants = NULL;
5442         skinframe->shirt = NULL;
5443         skinframe->nmap = NULL;
5444         skinframe->gloss = NULL;
5445         skinframe->glow = NULL;
5446         skinframe->fog = NULL;
5447         skinframe->hasalpha = false;
5448
5449         skinframe->avgcolor[0] = rand() / RAND_MAX;
5450         skinframe->avgcolor[1] = rand() / RAND_MAX;
5451         skinframe->avgcolor[2] = rand() / RAND_MAX;
5452         skinframe->avgcolor[3] = 1;
5453
5454         return skinframe;
5455 }
5456
5457 void R_Main_FreeViewCache(void)
5458 {
5459         if (r_refdef.viewcache.entityvisible)
5460                 Mem_Free(r_refdef.viewcache.entityvisible);
5461         if (r_refdef.viewcache.world_pvsbits)
5462                 Mem_Free(r_refdef.viewcache.world_pvsbits);
5463         if (r_refdef.viewcache.world_leafvisible)
5464                 Mem_Free(r_refdef.viewcache.world_leafvisible);
5465         if (r_refdef.viewcache.world_surfacevisible)
5466                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
5467         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
5468 }
5469
5470 void R_Main_ResizeViewCache(void)
5471 {
5472         int numentities = r_refdef.scene.numentities;
5473         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
5474         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
5475         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
5476         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
5477         if (r_refdef.viewcache.maxentities < numentities)
5478         {
5479                 r_refdef.viewcache.maxentities = numentities;
5480                 if (r_refdef.viewcache.entityvisible)
5481                         Mem_Free(r_refdef.viewcache.entityvisible);
5482                 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
5483         }
5484         if (r_refdef.viewcache.world_numclusters != numclusters)
5485         {
5486                 r_refdef.viewcache.world_numclusters = numclusters;
5487                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
5488                 if (r_refdef.viewcache.world_pvsbits)
5489                         Mem_Free(r_refdef.viewcache.world_pvsbits);
5490                 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
5491         }
5492         if (r_refdef.viewcache.world_numleafs != numleafs)
5493         {
5494                 r_refdef.viewcache.world_numleafs = numleafs;
5495                 if (r_refdef.viewcache.world_leafvisible)
5496                         Mem_Free(r_refdef.viewcache.world_leafvisible);
5497                 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
5498         }
5499         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
5500         {
5501                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
5502                 if (r_refdef.viewcache.world_surfacevisible)
5503                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
5504                 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
5505         }
5506 }
5507
5508 extern rtexture_t *loadingscreentexture;
5509 void gl_main_start(void)
5510 {
5511         loadingscreentexture = NULL;
5512         r_texture_blanknormalmap = NULL;
5513         r_texture_white = NULL;
5514         r_texture_grey128 = NULL;
5515         r_texture_black = NULL;
5516         r_texture_whitecube = NULL;
5517         r_texture_normalizationcube = NULL;
5518         r_texture_fogattenuation = NULL;
5519         r_texture_gammaramps = NULL;
5520
5521         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
5522         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
5523
5524         switch(vid.renderpath)
5525         {
5526         case RENDERPATH_GL20:
5527         case RENDERPATH_CGGL:
5528                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5529                 Cvar_SetValueQuick(&gl_combine, 1);
5530                 Cvar_SetValueQuick(&r_glsl, 1);
5531                 r_loadnormalmap = true;
5532                 r_loadgloss = true;
5533                 r_loadfog = false;
5534                 break;
5535         case RENDERPATH_GL13:
5536                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5537                 Cvar_SetValueQuick(&gl_combine, 1);
5538                 Cvar_SetValueQuick(&r_glsl, 0);
5539                 r_loadnormalmap = false;
5540                 r_loadgloss = false;
5541                 r_loadfog = true;
5542                 break;
5543         case RENDERPATH_GL11:
5544                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5545                 Cvar_SetValueQuick(&gl_combine, 0);
5546                 Cvar_SetValueQuick(&r_glsl, 0);
5547                 r_loadnormalmap = false;
5548                 r_loadgloss = false;
5549                 r_loadfog = true;
5550                 break;
5551         }
5552
5553         R_AnimCache_Free();
5554         R_FrameData_Reset();
5555
5556         r_numqueries = 0;
5557         r_maxqueries = 0;
5558         memset(r_queries, 0, sizeof(r_queries));
5559
5560         r_qwskincache = NULL;
5561         r_qwskincache_size = 0;
5562
5563         // set up r_skinframe loading system for textures
5564         memset(&r_skinframe, 0, sizeof(r_skinframe));
5565         r_skinframe.loadsequence = 1;
5566         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
5567
5568         r_main_texturepool = R_AllocTexturePool();
5569         R_BuildBlankTextures();
5570         R_BuildNoTexture();
5571         if (vid.support.arb_texture_cube_map)
5572         {
5573                 R_BuildWhiteCube();
5574                 R_BuildNormalizationCube();
5575         }
5576         r_texture_fogattenuation = NULL;
5577         r_texture_gammaramps = NULL;
5578         //r_texture_fogintensity = NULL;
5579         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
5580         memset(&r_waterstate, 0, sizeof(r_waterstate));
5581         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5582         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
5583 #ifdef SUPPORTCG
5584         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5585         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
5586 #endif
5587         memset(&r_svbsp, 0, sizeof (r_svbsp));
5588
5589         r_refdef.fogmasktable_density = 0;
5590 }
5591
5592 void gl_main_shutdown(void)
5593 {
5594         R_AnimCache_Free();
5595         R_FrameData_Reset();
5596
5597         R_Main_FreeViewCache();
5598
5599         if (r_maxqueries)
5600                 qglDeleteQueriesARB(r_maxqueries, r_queries);
5601
5602         r_numqueries = 0;
5603         r_maxqueries = 0;
5604         memset(r_queries, 0, sizeof(r_queries));
5605
5606         r_qwskincache = NULL;
5607         r_qwskincache_size = 0;
5608
5609         // clear out the r_skinframe state
5610         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
5611         memset(&r_skinframe, 0, sizeof(r_skinframe));
5612
5613         if (r_svbsp.nodes)
5614                 Mem_Free(r_svbsp.nodes);
5615         memset(&r_svbsp, 0, sizeof (r_svbsp));
5616         R_FreeTexturePool(&r_main_texturepool);
5617         loadingscreentexture = NULL;
5618         r_texture_blanknormalmap = NULL;
5619         r_texture_white = NULL;
5620         r_texture_grey128 = NULL;
5621         r_texture_black = NULL;
5622         r_texture_whitecube = NULL;
5623         r_texture_normalizationcube = NULL;
5624         r_texture_fogattenuation = NULL;
5625         r_texture_gammaramps = NULL;
5626         //r_texture_fogintensity = NULL;
5627         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
5628         memset(&r_waterstate, 0, sizeof(r_waterstate));
5629         R_GLSL_Restart_f();
5630 }
5631
5632 extern void CL_ParseEntityLump(char *entitystring);
5633 void gl_main_newmap(void)
5634 {
5635         // FIXME: move this code to client
5636         int l;
5637         char *entities, entname[MAX_QPATH];
5638         if (r_qwskincache)
5639                 Mem_Free(r_qwskincache);
5640         r_qwskincache = NULL;
5641         r_qwskincache_size = 0;
5642         if (cl.worldmodel)
5643         {
5644                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
5645                 l = (int)strlen(entname) - 4;
5646                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
5647                 {
5648                         memcpy(entname + l, ".ent", 5);
5649                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
5650                         {
5651                                 CL_ParseEntityLump(entities);
5652                                 Mem_Free(entities);
5653                                 return;
5654                         }
5655                 }
5656                 if (cl.worldmodel->brush.entities)
5657                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
5658         }
5659         R_Main_FreeViewCache();
5660
5661         R_FrameData_Reset();
5662 }
5663
5664 void GL_Main_Init(void)
5665 {
5666         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
5667
5668         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
5669         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
5670         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
5671         if (gamemode == GAME_NEHAHRA)
5672         {
5673                 Cvar_RegisterVariable (&gl_fogenable);
5674                 Cvar_RegisterVariable (&gl_fogdensity);
5675                 Cvar_RegisterVariable (&gl_fogred);
5676                 Cvar_RegisterVariable (&gl_foggreen);
5677                 Cvar_RegisterVariable (&gl_fogblue);
5678                 Cvar_RegisterVariable (&gl_fogstart);
5679                 Cvar_RegisterVariable (&gl_fogend);
5680                 Cvar_RegisterVariable (&gl_skyclip);
5681         }
5682         Cvar_RegisterVariable(&r_motionblur);
5683         Cvar_RegisterVariable(&r_motionblur_maxblur);
5684         Cvar_RegisterVariable(&r_motionblur_bmin);
5685         Cvar_RegisterVariable(&r_motionblur_vmin);
5686         Cvar_RegisterVariable(&r_motionblur_vmax);
5687         Cvar_RegisterVariable(&r_motionblur_vcoeff);
5688         Cvar_RegisterVariable(&r_motionblur_randomize);
5689         Cvar_RegisterVariable(&r_damageblur);
5690         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
5691         Cvar_RegisterVariable(&r_equalize_entities_minambient);
5692         Cvar_RegisterVariable(&r_equalize_entities_by);
5693         Cvar_RegisterVariable(&r_equalize_entities_to);
5694         Cvar_RegisterVariable(&r_depthfirst);
5695         Cvar_RegisterVariable(&r_useinfinitefarclip);
5696         Cvar_RegisterVariable(&r_farclip_base);
5697         Cvar_RegisterVariable(&r_farclip_world);
5698         Cvar_RegisterVariable(&r_nearclip);
5699         Cvar_RegisterVariable(&r_showbboxes);
5700         Cvar_RegisterVariable(&r_showsurfaces);
5701         Cvar_RegisterVariable(&r_showtris);
5702         Cvar_RegisterVariable(&r_shownormals);
5703         Cvar_RegisterVariable(&r_showlighting);
5704         Cvar_RegisterVariable(&r_showshadowvolumes);
5705         Cvar_RegisterVariable(&r_showcollisionbrushes);
5706         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
5707         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
5708         Cvar_RegisterVariable(&r_showdisabledepthtest);
5709         Cvar_RegisterVariable(&r_drawportals);
5710         Cvar_RegisterVariable(&r_drawentities);
5711         Cvar_RegisterVariable(&r_cullentities_trace);
5712         Cvar_RegisterVariable(&r_cullentities_trace_samples);
5713         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
5714         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
5715         Cvar_RegisterVariable(&r_cullentities_trace_delay);
5716         Cvar_RegisterVariable(&r_drawviewmodel);
5717         Cvar_RegisterVariable(&r_speeds);
5718         Cvar_RegisterVariable(&r_fullbrights);
5719         Cvar_RegisterVariable(&r_wateralpha);
5720         Cvar_RegisterVariable(&r_dynamic);
5721         Cvar_RegisterVariable(&r_fullbright);
5722         Cvar_RegisterVariable(&r_shadows);
5723         Cvar_RegisterVariable(&r_shadows_darken);
5724         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
5725         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
5726         Cvar_RegisterVariable(&r_shadows_throwdistance);
5727         Cvar_RegisterVariable(&r_shadows_throwdirection);
5728         Cvar_RegisterVariable(&r_q1bsp_skymasking);
5729         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
5730         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
5731         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
5732         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
5733         Cvar_RegisterVariable(&r_fog_exp2);
5734         Cvar_RegisterVariable(&r_drawfog);
5735         Cvar_RegisterVariable(&r_transparentdepthmasking);
5736         Cvar_RegisterVariable(&r_texture_dds_load);
5737         Cvar_RegisterVariable(&r_texture_dds_save);
5738         Cvar_RegisterVariable(&r_textureunits);
5739         Cvar_RegisterVariable(&gl_combine);
5740         Cvar_RegisterVariable(&r_glsl);
5741         Cvar_RegisterVariable(&r_glsl_deluxemapping);
5742         Cvar_RegisterVariable(&r_glsl_offsetmapping);
5743         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
5744         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
5745         Cvar_RegisterVariable(&r_glsl_postprocess);
5746         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
5747         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
5748         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
5749         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
5750         Cvar_RegisterVariable(&r_water);
5751         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
5752         Cvar_RegisterVariable(&r_water_clippingplanebias);
5753         Cvar_RegisterVariable(&r_water_refractdistort);
5754         Cvar_RegisterVariable(&r_water_reflectdistort);
5755         Cvar_RegisterVariable(&r_lerpsprites);
5756         Cvar_RegisterVariable(&r_lerpmodels);
5757         Cvar_RegisterVariable(&r_lerplightstyles);
5758         Cvar_RegisterVariable(&r_waterscroll);
5759         Cvar_RegisterVariable(&r_bloom);
5760         Cvar_RegisterVariable(&r_bloom_colorscale);
5761         Cvar_RegisterVariable(&r_bloom_brighten);
5762         Cvar_RegisterVariable(&r_bloom_blur);
5763         Cvar_RegisterVariable(&r_bloom_resolution);
5764         Cvar_RegisterVariable(&r_bloom_colorexponent);
5765         Cvar_RegisterVariable(&r_bloom_colorsubtract);
5766         Cvar_RegisterVariable(&r_hdr);
5767         Cvar_RegisterVariable(&r_hdr_scenebrightness);
5768         Cvar_RegisterVariable(&r_hdr_glowintensity);
5769         Cvar_RegisterVariable(&r_hdr_range);
5770         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
5771         Cvar_RegisterVariable(&developer_texturelogging);
5772         Cvar_RegisterVariable(&gl_lightmaps);
5773         Cvar_RegisterVariable(&r_test);
5774         Cvar_RegisterVariable(&r_batchmode);
5775         Cvar_RegisterVariable(&r_glsl_saturation);
5776         Cvar_RegisterVariable(&r_framedatasize);
5777         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
5778                 Cvar_SetValue("r_fullbrights", 0);
5779         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
5780
5781         Cvar_RegisterVariable(&r_track_sprites);
5782         Cvar_RegisterVariable(&r_track_sprites_flags);
5783         Cvar_RegisterVariable(&r_track_sprites_scalew);
5784         Cvar_RegisterVariable(&r_track_sprites_scaleh);
5785 }
5786
5787 extern void R_Textures_Init(void);
5788 extern void GL_Draw_Init(void);
5789 extern void GL_Main_Init(void);
5790 extern void R_Shadow_Init(void);
5791 extern void R_Sky_Init(void);
5792 extern void GL_Surf_Init(void);
5793 extern void R_Particles_Init(void);
5794 extern void R_Explosion_Init(void);
5795 extern void gl_backend_init(void);
5796 extern void Sbar_Init(void);
5797 extern void R_LightningBeams_Init(void);
5798 extern void Mod_RenderInit(void);
5799 extern void Font_Init(void);
5800
5801 void Render_Init(void)
5802 {
5803         gl_backend_init();
5804         R_Textures_Init();
5805         GL_Main_Init();
5806         Font_Init();
5807         GL_Draw_Init();
5808         R_Shadow_Init();
5809         R_Sky_Init();
5810         GL_Surf_Init();
5811         Sbar_Init();
5812         R_Particles_Init();
5813         R_Explosion_Init();
5814         R_LightningBeams_Init();
5815         Mod_RenderInit();
5816 }
5817
5818 /*
5819 ===============
5820 GL_Init
5821 ===============
5822 */
5823 extern char *ENGINE_EXTENSIONS;
5824 void GL_Init (void)
5825 {
5826         gl_renderer = (const char *)qglGetString(GL_RENDERER);
5827         gl_vendor = (const char *)qglGetString(GL_VENDOR);
5828         gl_version = (const char *)qglGetString(GL_VERSION);
5829         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
5830
5831         if (!gl_extensions)
5832                 gl_extensions = "";
5833         if (!gl_platformextensions)
5834                 gl_platformextensions = "";
5835
5836         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
5837         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
5838         Con_Printf("GL_VERSION: %s\n", gl_version);
5839         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
5840         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
5841
5842         VID_CheckExtensions();
5843
5844         // LordHavoc: report supported extensions
5845         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
5846
5847         // clear to black (loading plaque will be seen over this)
5848         CHECKGLERROR
5849         qglClearColor(0,0,0,1);CHECKGLERROR
5850         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
5851 }
5852
5853 int R_CullBox(const vec3_t mins, const vec3_t maxs)
5854 {
5855         int i;
5856         mplane_t *p;
5857         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5858         {
5859                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
5860                 if (i == 4)
5861                         continue;
5862                 p = r_refdef.view.frustum + i;
5863                 switch(p->signbits)
5864                 {
5865                 default:
5866                 case 0:
5867                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5868                                 return true;
5869                         break;
5870                 case 1:
5871                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5872                                 return true;
5873                         break;
5874                 case 2:
5875                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5876                                 return true;
5877                         break;
5878                 case 3:
5879                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5880                                 return true;
5881                         break;
5882                 case 4:
5883                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5884                                 return true;
5885                         break;
5886                 case 5:
5887                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5888                                 return true;
5889                         break;
5890                 case 6:
5891                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5892                                 return true;
5893                         break;
5894                 case 7:
5895                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5896                                 return true;
5897                         break;
5898                 }
5899         }
5900         return false;
5901 }
5902
5903 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
5904 {
5905         int i;
5906         const mplane_t *p;
5907         for (i = 0;i < numplanes;i++)
5908         {
5909                 p = planes + i;
5910                 switch(p->signbits)
5911                 {
5912                 default:
5913                 case 0:
5914                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5915                                 return true;
5916                         break;
5917                 case 1:
5918                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5919                                 return true;
5920                         break;
5921                 case 2:
5922                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5923                                 return true;
5924                         break;
5925                 case 3:
5926                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5927                                 return true;
5928                         break;
5929                 case 4:
5930                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5931                                 return true;
5932                         break;
5933                 case 5:
5934                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5935                                 return true;
5936                         break;
5937                 case 6:
5938                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5939                                 return true;
5940                         break;
5941                 case 7:
5942                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5943                                 return true;
5944                         break;
5945                 }
5946         }
5947         return false;
5948 }
5949
5950 //==================================================================================
5951
5952 // LordHavoc: this stores temporary data used within the same frame
5953
5954 qboolean r_framedata_failed;
5955 static size_t r_framedata_size;
5956 static size_t r_framedata_current;
5957 static void *r_framedata_base;
5958
5959 void R_FrameData_Reset(void)
5960 {
5961         if (r_framedata_base)
5962                 Mem_Free(r_framedata_base);
5963         r_framedata_base = NULL;
5964         r_framedata_size = 0;
5965         r_framedata_current = 0;
5966         r_framedata_failed = false;
5967 }
5968
5969 void R_FrameData_NewFrame(void)
5970 {
5971         size_t wantedsize;
5972         if (r_framedata_failed)
5973                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
5974         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
5975         wantedsize = bound(65536, wantedsize, 128*1024*1024);
5976         if (r_framedata_size != wantedsize)
5977         {
5978                 r_framedata_size = wantedsize;
5979                 if (r_framedata_base)
5980                         Mem_Free(r_framedata_base);
5981                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
5982         }
5983         r_framedata_current = 0;
5984         r_framedata_failed = false;
5985 }
5986
5987 void *R_FrameData_Alloc(size_t size)
5988 {
5989         void *data;
5990
5991         // align to 16 byte boundary
5992         size = (size + 15) & ~15;
5993         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
5994         r_framedata_current += size;
5995
5996         // check overflow
5997         if (r_framedata_current > r_framedata_size)
5998                 r_framedata_failed = true;
5999
6000         // return NULL on everything after a failure
6001         if (r_framedata_failed)
6002                 return NULL;
6003
6004         return data;
6005 }
6006
6007 void *R_FrameData_Store(size_t size, void *data)
6008 {
6009         void *d = R_FrameData_Alloc(size);
6010         if (d)
6011                 memcpy(d, data, size);
6012         return d;
6013 }
6014
6015 //==================================================================================
6016
6017 // LordHavoc: animcache originally written by Echon, rewritten since then
6018
6019 /**
6020  * Animation cache prevents re-generating mesh data for an animated model
6021  * multiple times in one frame for lighting, shadowing, reflections, etc.
6022  */
6023
6024 void R_AnimCache_Free(void)
6025 {
6026 }
6027
6028 void R_AnimCache_ClearCache(void)
6029 {
6030         int i;
6031         entity_render_t *ent;
6032
6033         for (i = 0;i < r_refdef.scene.numentities;i++)
6034         {
6035                 ent = r_refdef.scene.entities[i];
6036                 ent->animcache_vertex3f = NULL;
6037                 ent->animcache_normal3f = NULL;
6038                 ent->animcache_svector3f = NULL;
6039                 ent->animcache_tvector3f = NULL;
6040         }
6041 }
6042
6043 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6044 {
6045         dp_model_t *model = ent->model;
6046         int numvertices;
6047         // see if it's already cached this frame
6048         if (ent->animcache_vertex3f)
6049         {
6050                 // add normals/tangents if needed
6051                 if (wantnormals || wanttangents)
6052                 {
6053                         if (ent->animcache_normal3f)
6054                                 wantnormals = false;
6055                         if (ent->animcache_svector3f)
6056                                 wanttangents = false;
6057                         if (wantnormals || wanttangents)
6058                         {
6059                                 numvertices = model->surfmesh.num_vertices;
6060                                 if (wantnormals)
6061                                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6062                                 if (wanttangents)
6063                                 {
6064                                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6065                                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6066                                 }
6067                                 if (!r_framedata_failed)
6068                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
6069                         }
6070                 }
6071         }
6072         else
6073         {
6074                 // see if this ent is worth caching
6075                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
6076                         return false;
6077                 // get some memory for this entity and generate mesh data
6078                 numvertices = model->surfmesh.num_vertices;
6079                 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6080                 if (wantnormals)
6081                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6082                 if (wanttangents)
6083                 {
6084                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6085                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6086                 }
6087                 if (!r_framedata_failed)
6088                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
6089         }
6090         return !r_framedata_failed;
6091 }
6092
6093 void R_AnimCache_CacheVisibleEntities(void)
6094 {
6095         int i;
6096         qboolean wantnormals = !r_showsurfaces.integer;
6097         qboolean wanttangents = !r_showsurfaces.integer;
6098
6099         switch(vid.renderpath)
6100         {
6101         case RENDERPATH_GL20:
6102         case RENDERPATH_CGGL:
6103                 break;
6104         case RENDERPATH_GL13:
6105         case RENDERPATH_GL11:
6106                 wanttangents = false;
6107                 break;
6108         }
6109
6110         // TODO: thread this
6111         // NOTE: R_PrepareRTLights() also caches entities
6112
6113         for (i = 0;i < r_refdef.scene.numentities;i++)
6114                 if (r_refdef.viewcache.entityvisible[i])
6115                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
6116
6117         if (r_shadows.integer)
6118                 for (i = 0;i < r_refdef.scene.numentities;i++)
6119                         if (!r_refdef.viewcache.entityvisible[i])
6120                                 R_AnimCache_GetEntity(r_refdef.scene.entities[i], false, false);
6121 }
6122
6123 //==================================================================================
6124
6125 static void R_View_UpdateEntityLighting (void)
6126 {
6127         int i;
6128         entity_render_t *ent;
6129         vec3_t tempdiffusenormal, avg;
6130         vec_t f, fa, fd, fdd;
6131
6132         for (i = 0;i < r_refdef.scene.numentities;i++)
6133         {
6134                 ent = r_refdef.scene.entities[i];
6135
6136                 // skip unseen models
6137                 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
6138                         continue;
6139
6140                 // skip bsp models
6141                 if (ent->model && ent->model->brush.num_leafs)
6142                 {
6143                         // TODO: use modellight for r_ambient settings on world?
6144                         VectorSet(ent->modellight_ambient, 0, 0, 0);
6145                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
6146                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
6147                         continue;
6148                 }
6149
6150                 // fetch the lighting from the worldmodel data
6151                 VectorClear(ent->modellight_ambient);
6152                 VectorClear(ent->modellight_diffuse);
6153                 VectorClear(tempdiffusenormal);
6154                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
6155                 {
6156                         vec3_t org;
6157                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6158                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
6159                         if(ent->flags & RENDER_EQUALIZE)
6160                         {
6161                                 // first fix up ambient lighting...
6162                                 if(r_equalize_entities_minambient.value > 0)
6163                                 {
6164                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
6165                                         if(fd > 0)
6166                                         {
6167                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
6168                                                 if(fa < r_equalize_entities_minambient.value * fd)
6169                                                 {
6170                                                         // solve:
6171                                                         //   fa'/fd' = minambient
6172                                                         //   fa'+0.25*fd' = fa+0.25*fd
6173                                                         //   ...
6174                                                         //   fa' = fd' * minambient
6175                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
6176                                                         //   ...
6177                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
6178                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
6179                                                         //   ...
6180                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
6181                                                         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
6182                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
6183                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6184                                                 }
6185                                         }
6186                                 }
6187
6188                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
6189                                 {
6190                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
6191                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
6192                                         if(f > 0)
6193                                         {
6194                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
6195                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
6196                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6197                                         }
6198                                 }
6199                         }
6200                 }
6201                 else // highly rare
6202                         VectorSet(ent->modellight_ambient, 1, 1, 1);
6203
6204                 // move the light direction into modelspace coordinates for lighting code
6205                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
6206                 if(VectorLength2(ent->modellight_lightdir) == 0)
6207                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
6208                 VectorNormalize(ent->modellight_lightdir);
6209         }
6210 }
6211
6212 #define MAX_LINEOFSIGHTTRACES 64
6213
6214 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
6215 {
6216         int i;
6217         vec3_t boxmins, boxmaxs;
6218         vec3_t start;
6219         vec3_t end;
6220         dp_model_t *model = r_refdef.scene.worldmodel;
6221
6222         if (!model || !model->brush.TraceLineOfSight)
6223                 return true;
6224
6225         // expand the box a little
6226         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
6227         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
6228         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
6229         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
6230         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
6231         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
6232
6233         // try center
6234         VectorCopy(eye, start);
6235         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
6236         if (model->brush.TraceLineOfSight(model, start, end))
6237                 return true;
6238
6239         // try various random positions
6240         for (i = 0;i < numsamples;i++)
6241         {
6242                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
6243                 if (model->brush.TraceLineOfSight(model, start, end))
6244                         return true;
6245         }
6246
6247         return false;
6248 }
6249
6250
6251 static void R_View_UpdateEntityVisible (void)
6252 {
6253         int i;
6254         int renderimask;
6255         int samples;
6256         entity_render_t *ent;
6257
6258         renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
6259         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
6260         {
6261                 // worldmodel can check visibility
6262                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
6263                 for (i = 0;i < r_refdef.scene.numentities;i++)
6264                 {
6265                         ent = r_refdef.scene.entities[i];
6266                         if (!(ent->flags & renderimask))
6267                         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)))
6268                         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))
6269                                 r_refdef.viewcache.entityvisible[i] = true;
6270                 }
6271                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
6272                 {
6273                         for (i = 0;i < r_refdef.scene.numentities;i++)
6274                         {
6275                                 ent = r_refdef.scene.entities[i];
6276                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
6277                                 {
6278                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
6279                                         if (samples < 0)
6280                                                 continue; // temp entities do pvs only
6281                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
6282                                                 ent->last_trace_visibility = realtime;
6283                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
6284                                                 r_refdef.viewcache.entityvisible[i] = 0;
6285                                 }
6286                         }
6287                 }
6288         }
6289         else
6290         {
6291                 // no worldmodel or it can't check visibility
6292                 for (i = 0;i < r_refdef.scene.numentities;i++)
6293                 {
6294                         ent = r_refdef.scene.entities[i];
6295                         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));
6296                 }
6297         }
6298 }
6299
6300 /// only used if skyrendermasked, and normally returns false
6301 int R_DrawBrushModelsSky (void)
6302 {
6303         int i, sky;
6304         entity_render_t *ent;
6305
6306         sky = false;
6307         for (i = 0;i < r_refdef.scene.numentities;i++)
6308         {
6309                 if (!r_refdef.viewcache.entityvisible[i])
6310                         continue;
6311                 ent = r_refdef.scene.entities[i];
6312                 if (!ent->model || !ent->model->DrawSky)
6313                         continue;
6314                 ent->model->DrawSky(ent);
6315                 sky = true;
6316         }
6317         return sky;
6318 }
6319
6320 static void R_DrawNoModel(entity_render_t *ent);
6321 static void R_DrawModels(void)
6322 {
6323         int i;
6324         entity_render_t *ent;
6325
6326         for (i = 0;i < r_refdef.scene.numentities;i++)
6327         {
6328                 if (!r_refdef.viewcache.entityvisible[i])
6329                         continue;
6330                 ent = r_refdef.scene.entities[i];
6331                 r_refdef.stats.entities++;
6332                 if (ent->model && ent->model->Draw != NULL)
6333                         ent->model->Draw(ent);
6334                 else
6335                         R_DrawNoModel(ent);
6336         }
6337 }
6338
6339 static void R_DrawModelsDepth(void)
6340 {
6341         int i;
6342         entity_render_t *ent;
6343
6344         for (i = 0;i < r_refdef.scene.numentities;i++)
6345         {
6346                 if (!r_refdef.viewcache.entityvisible[i])
6347                         continue;
6348                 ent = r_refdef.scene.entities[i];
6349                 if (ent->model && ent->model->DrawDepth != NULL)
6350                         ent->model->DrawDepth(ent);
6351         }
6352 }
6353
6354 static void R_DrawModelsDebug(void)
6355 {
6356         int i;
6357         entity_render_t *ent;
6358
6359         for (i = 0;i < r_refdef.scene.numentities;i++)
6360         {
6361                 if (!r_refdef.viewcache.entityvisible[i])
6362                         continue;
6363                 ent = r_refdef.scene.entities[i];
6364                 if (ent->model && ent->model->DrawDebug != NULL)
6365                         ent->model->DrawDebug(ent);
6366         }
6367 }
6368
6369 static void R_DrawModelsAddWaterPlanes(void)
6370 {
6371         int i;
6372         entity_render_t *ent;
6373
6374         for (i = 0;i < r_refdef.scene.numentities;i++)
6375         {
6376                 if (!r_refdef.viewcache.entityvisible[i])
6377                         continue;
6378                 ent = r_refdef.scene.entities[i];
6379                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
6380                         ent->model->DrawAddWaterPlanes(ent);
6381         }
6382 }
6383
6384 static void R_View_SetFrustum(void)
6385 {
6386         int i;
6387         double slopex, slopey;
6388         vec3_t forward, left, up, origin;
6389
6390         // we can't trust r_refdef.view.forward and friends in reflected scenes
6391         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
6392
6393 #if 0
6394         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
6395         r_refdef.view.frustum[0].normal[1] = 0 - 0;
6396         r_refdef.view.frustum[0].normal[2] = -1 - 0;
6397         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
6398         r_refdef.view.frustum[1].normal[1] = 0 + 0;
6399         r_refdef.view.frustum[1].normal[2] = -1 + 0;
6400         r_refdef.view.frustum[2].normal[0] = 0 - 0;
6401         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
6402         r_refdef.view.frustum[2].normal[2] = -1 - 0;
6403         r_refdef.view.frustum[3].normal[0] = 0 + 0;
6404         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
6405         r_refdef.view.frustum[3].normal[2] = -1 + 0;
6406 #endif
6407
6408 #if 0
6409         zNear = r_refdef.nearclip;
6410         nudge = 1.0 - 1.0 / (1<<23);
6411         r_refdef.view.frustum[4].normal[0] = 0 - 0;
6412         r_refdef.view.frustum[4].normal[1] = 0 - 0;
6413         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
6414         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
6415         r_refdef.view.frustum[5].normal[0] = 0 + 0;
6416         r_refdef.view.frustum[5].normal[1] = 0 + 0;
6417         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
6418         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
6419 #endif
6420
6421
6422
6423 #if 0
6424         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
6425         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
6426         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
6427         r_refdef.view.frustum[0].dist = m[15] - m[12];
6428
6429         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
6430         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
6431         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
6432         r_refdef.view.frustum[1].dist = m[15] + m[12];
6433
6434         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
6435         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
6436         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
6437         r_refdef.view.frustum[2].dist = m[15] - m[13];
6438
6439         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
6440         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
6441         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
6442         r_refdef.view.frustum[3].dist = m[15] + m[13];
6443
6444         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
6445         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
6446         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
6447         r_refdef.view.frustum[4].dist = m[15] - m[14];
6448
6449         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
6450         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
6451         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
6452         r_refdef.view.frustum[5].dist = m[15] + m[14];
6453 #endif
6454
6455         if (r_refdef.view.useperspective)
6456         {
6457                 slopex = 1.0 / r_refdef.view.frustum_x;
6458                 slopey = 1.0 / r_refdef.view.frustum_y;
6459                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
6460                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
6461                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
6462                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
6463                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6464
6465                 // Leaving those out was a mistake, those were in the old code, and they
6466                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
6467                 // I couldn't reproduce it after adding those normalizations. --blub
6468                 VectorNormalize(r_refdef.view.frustum[0].normal);
6469                 VectorNormalize(r_refdef.view.frustum[1].normal);
6470                 VectorNormalize(r_refdef.view.frustum[2].normal);
6471                 VectorNormalize(r_refdef.view.frustum[3].normal);
6472
6473                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
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[0]);
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[1]);
6476                 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]);
6477                 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]);
6478
6479                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
6480                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
6481                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
6482                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
6483                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6484         }
6485         else
6486         {
6487                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
6488                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
6489                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
6490                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
6491                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6492                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
6493                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
6494                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
6495                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
6496                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6497         }
6498         r_refdef.view.numfrustumplanes = 5;
6499
6500         if (r_refdef.view.useclipplane)
6501         {
6502                 r_refdef.view.numfrustumplanes = 6;
6503                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
6504         }
6505
6506         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6507                 PlaneClassify(r_refdef.view.frustum + i);
6508
6509         // LordHavoc: note to all quake engine coders, Quake had a special case
6510         // for 90 degrees which assumed a square view (wrong), so I removed it,
6511         // Quake2 has it disabled as well.
6512
6513         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
6514         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
6515         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
6516         //PlaneClassify(&frustum[0]);
6517
6518         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
6519         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
6520         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
6521         //PlaneClassify(&frustum[1]);
6522
6523         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
6524         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
6525         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
6526         //PlaneClassify(&frustum[2]);
6527
6528         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
6529         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
6530         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
6531         //PlaneClassify(&frustum[3]);
6532
6533         // nearclip plane
6534         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
6535         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
6536         //PlaneClassify(&frustum[4]);
6537 }
6538
6539 void R_View_Update(void)
6540 {
6541         R_Main_ResizeViewCache();
6542         R_View_SetFrustum();
6543         R_View_WorldVisibility(r_refdef.view.useclipplane);
6544         R_View_UpdateEntityVisible();
6545         R_View_UpdateEntityLighting();
6546 }
6547
6548 void R_SetupView(qboolean allowwaterclippingplane)
6549 {
6550         const float *customclipplane = NULL;
6551         float plane[4];
6552         if (r_refdef.view.useclipplane && allowwaterclippingplane)
6553         {
6554                 // LordHavoc: couldn't figure out how to make this approach the
6555                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
6556                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
6557                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
6558                         dist = r_refdef.view.clipplane.dist;
6559                 plane[0] = r_refdef.view.clipplane.normal[0];
6560                 plane[1] = r_refdef.view.clipplane.normal[1];
6561                 plane[2] = r_refdef.view.clipplane.normal[2];
6562                 plane[3] = dist;
6563                 customclipplane = plane;
6564         }
6565
6566         if (!r_refdef.view.useperspective)
6567                 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);
6568         else if (vid.stencil && r_useinfinitefarclip.integer)
6569                 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);
6570         else
6571                 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);
6572         R_SetViewport(&r_refdef.view.viewport);
6573 }
6574
6575 void R_EntityMatrix(const matrix4x4_t *matrix)
6576 {
6577         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
6578         {
6579                 gl_modelmatrixchanged = false;
6580                 gl_modelmatrix = *matrix;
6581                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
6582                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
6583                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
6584                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
6585                 CHECKGLERROR
6586                 switch(vid.renderpath)
6587                 {
6588                 case RENDERPATH_GL20:
6589                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
6590                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6591                         break;
6592                 case RENDERPATH_CGGL:
6593 #ifdef SUPPORTCG
6594                         CHECKCGERROR
6595                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);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                 // render the normal view scene and copy into texture
6847                 // (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)
6848                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6849                 {
6850                         r_refdef.view = myview;
6851                         r_refdef.view.clipplane = p->plane;
6852                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6853                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6854                         PlaneClassify(&r_refdef.view.clipplane);
6855
6856                         R_ResetViewRendering3D();
6857                         R_ClearScreen(r_refdef.fogenabled);
6858                         R_View_Update();
6859                         R_RenderScene();
6860
6861                         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);
6862                 }
6863
6864                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6865                 {
6866                         r_refdef.view = myview;
6867                         // render reflected scene and copy into texture
6868                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6869                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6870                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6871                         r_refdef.view.clipplane = p->plane;
6872                         // reverse the cullface settings for this render
6873                         r_refdef.view.cullface_front = GL_FRONT;
6874                         r_refdef.view.cullface_back = GL_BACK;
6875                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6876                         {
6877                                 r_refdef.view.usecustompvs = true;
6878                                 if (p->pvsvalid)
6879                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6880                                 else
6881                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6882                         }
6883
6884                         R_ResetViewRendering3D();
6885                         R_ClearScreen(r_refdef.fogenabled);
6886                         R_View_Update();
6887                         R_RenderScene();
6888
6889                         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);
6890                 }
6891         }
6892         r_waterstate.renderingscene = false;
6893         r_refdef.view = originalview;
6894         R_ResetViewRendering3D();
6895         R_ClearScreen(r_refdef.fogenabled);
6896         R_View_Update();
6897         return;
6898 error:
6899         r_refdef.view = originalview;
6900         r_waterstate.renderingscene = false;
6901         Cvar_SetValueQuick(&r_water, 0);
6902         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6903         return;
6904 }
6905
6906 void R_Bloom_StartFrame(void)
6907 {
6908         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6909
6910         switch(vid.renderpath)
6911         {
6912         case RENDERPATH_GL20:
6913         case RENDERPATH_CGGL:
6914                 break;
6915         case RENDERPATH_GL13:
6916         case RENDERPATH_GL11:
6917                 return;
6918         }
6919
6920         // set bloomwidth and bloomheight to the bloom resolution that will be
6921         // used (often less than the screen resolution for faster rendering)
6922         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
6923         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
6924         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
6925         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
6926         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
6927
6928         // calculate desired texture sizes
6929         if (vid.support.arb_texture_non_power_of_two)
6930         {
6931                 screentexturewidth = r_refdef.view.width;
6932                 screentextureheight = r_refdef.view.height;
6933                 bloomtexturewidth = r_bloomstate.bloomwidth;
6934                 bloomtextureheight = r_bloomstate.bloomheight;
6935         }
6936         else
6937         {
6938                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
6939                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
6940                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
6941                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
6942         }
6943
6944         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))
6945         {
6946                 Cvar_SetValueQuick(&r_hdr, 0);
6947                 Cvar_SetValueQuick(&r_bloom, 0);
6948                 Cvar_SetValueQuick(&r_motionblur, 0);
6949                 Cvar_SetValueQuick(&r_damageblur, 0);
6950         }
6951
6952         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)))
6953                 screentexturewidth = screentextureheight = 0;
6954         if (!r_hdr.integer && !r_bloom.integer)
6955                 bloomtexturewidth = bloomtextureheight = 0;
6956
6957         // allocate textures as needed
6958         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
6959         {
6960                 if (r_bloomstate.texture_screen)
6961                         R_FreeTexture(r_bloomstate.texture_screen);
6962                 r_bloomstate.texture_screen = NULL;
6963                 r_bloomstate.screentexturewidth = screentexturewidth;
6964                 r_bloomstate.screentextureheight = screentextureheight;
6965                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
6966                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
6967         }
6968         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
6969         {
6970                 if (r_bloomstate.texture_bloom)
6971                         R_FreeTexture(r_bloomstate.texture_bloom);
6972                 r_bloomstate.texture_bloom = NULL;
6973                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6974                 r_bloomstate.bloomtextureheight = bloomtextureheight;
6975                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6976                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
6977         }
6978
6979         // when doing a reduced render (HDR) we want to use a smaller area
6980         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6981         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6982         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6983         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6984         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6985
6986         // set up a texcoord array for the full resolution screen image
6987         // (we have to keep this around to copy back during final render)
6988         r_bloomstate.screentexcoord2f[0] = 0;
6989         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
6990         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
6991         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
6992         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
6993         r_bloomstate.screentexcoord2f[5] = 0;
6994         r_bloomstate.screentexcoord2f[6] = 0;
6995         r_bloomstate.screentexcoord2f[7] = 0;
6996
6997         // set up a texcoord array for the reduced resolution bloom image
6998         // (which will be additive blended over the screen image)
6999         r_bloomstate.bloomtexcoord2f[0] = 0;
7000         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7001         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7002         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7003         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7004         r_bloomstate.bloomtexcoord2f[5] = 0;
7005         r_bloomstate.bloomtexcoord2f[6] = 0;
7006         r_bloomstate.bloomtexcoord2f[7] = 0;
7007
7008         if (r_hdr.integer || r_bloom.integer)
7009         {
7010                 r_bloomstate.enabled = true;
7011                 r_bloomstate.hdr = r_hdr.integer != 0;
7012         }
7013
7014         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);
7015 }
7016
7017 void R_Bloom_CopyBloomTexture(float colorscale)
7018 {
7019         r_refdef.stats.bloom++;
7020
7021         // scale down screen texture to the bloom texture size
7022         CHECKGLERROR
7023         R_SetViewport(&r_bloomstate.viewport);
7024         GL_BlendFunc(GL_ONE, GL_ZERO);
7025         GL_Color(colorscale, colorscale, colorscale, 1);
7026         // TODO: optimize with multitexture or GLSL
7027         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7028         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7029         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7030         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7031
7032         // we now have a bloom image in the framebuffer
7033         // copy it into the bloom image texture for later processing
7034         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);
7035         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7036 }
7037
7038 void R_Bloom_CopyHDRTexture(void)
7039 {
7040         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);
7041         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7042 }
7043
7044 void R_Bloom_MakeTexture(void)
7045 {
7046         int x, range, dir;
7047         float xoffset, yoffset, r, brighten;
7048
7049         r_refdef.stats.bloom++;
7050
7051         R_ResetViewRendering2D();
7052         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7053         R_Mesh_ColorPointer(NULL, 0, 0);
7054
7055         // we have a bloom image in the framebuffer
7056         CHECKGLERROR
7057         R_SetViewport(&r_bloomstate.viewport);
7058
7059         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
7060         {
7061                 x *= 2;
7062                 r = bound(0, r_bloom_colorexponent.value / x, 1);
7063                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7064                 GL_Color(r, r, r, 1);
7065                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7066                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7067                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7068                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7069
7070                 // copy the vertically blurred bloom view to a texture
7071                 GL_ActiveTexture(0);
7072                 CHECKGLERROR
7073                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
7074                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7075         }
7076
7077         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
7078         brighten = r_bloom_brighten.value;
7079         if (r_hdr.integer)
7080                 brighten *= r_hdr_range.value;
7081         brighten = sqrt(brighten);
7082         if(range >= 1)
7083                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
7084         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7085         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
7086
7087         for (dir = 0;dir < 2;dir++)
7088         {
7089                 // blend on at multiple vertical offsets to achieve a vertical blur
7090                 // TODO: do offset blends using GLSL
7091                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
7092                 GL_BlendFunc(GL_ONE, GL_ZERO);
7093                 for (x = -range;x <= range;x++)
7094                 {
7095                         if (!dir){xoffset = 0;yoffset = x;}
7096                         else {xoffset = x;yoffset = 0;}
7097                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
7098                         yoffset /= (float)r_bloomstate.bloomtextureheight;
7099                         // compute a texcoord array with the specified x and y offset
7100                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
7101                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7102                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7103                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7104                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7105                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
7106                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
7107                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
7108                         // this r value looks like a 'dot' particle, fading sharply to
7109                         // black at the edges
7110                         // (probably not realistic but looks good enough)
7111                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
7112                         //r = brighten/(range*2+1);
7113                         r = brighten / (range * 2 + 1);
7114                         if(range >= 1)
7115                                 r *= (1 - x*x/(float)(range*range));
7116                         GL_Color(r, r, r, 1);
7117                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7118                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7119                         GL_BlendFunc(GL_ONE, GL_ONE);
7120                 }
7121
7122                 // copy the vertically blurred bloom view to a texture
7123                 GL_ActiveTexture(0);
7124                 CHECKGLERROR
7125                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
7126                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7127         }
7128
7129         // apply subtract last
7130         // (just like it would be in a GLSL shader)
7131         if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
7132         {
7133                 GL_BlendFunc(GL_ONE, GL_ZERO);
7134                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7135                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7136                 GL_Color(1, 1, 1, 1);
7137                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7138                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7139
7140                 GL_BlendFunc(GL_ONE, GL_ONE);
7141                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
7142                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7143                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7144                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
7145                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7146                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7147                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
7148
7149                 // copy the darkened bloom view to a texture
7150                 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);
7151                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7152         }
7153 }
7154
7155 void R_HDR_RenderBloomTexture(void)
7156 {
7157         int oldwidth, oldheight;
7158         float oldcolorscale;
7159
7160         oldcolorscale = r_refdef.view.colorscale;
7161         oldwidth = r_refdef.view.width;
7162         oldheight = r_refdef.view.height;
7163         r_refdef.view.width = r_bloomstate.bloomwidth;
7164         r_refdef.view.height = r_bloomstate.bloomheight;
7165
7166         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
7167         // TODO: add exposure compensation features
7168         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
7169
7170         r_refdef.view.showdebug = false;
7171         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
7172
7173         R_ResetViewRendering3D();
7174
7175         R_ClearScreen(r_refdef.fogenabled);
7176         if (r_timereport_active)
7177                 R_TimeReport("HDRclear");
7178
7179         R_View_Update();
7180         if (r_timereport_active)
7181                 R_TimeReport("visibility");
7182
7183         // only do secondary renders with HDR if r_hdr is 2 or higher
7184         r_waterstate.numwaterplanes = 0;
7185         if (r_waterstate.enabled && r_hdr.integer >= 2)
7186                 R_RenderWaterPlanes();
7187
7188         r_refdef.view.showdebug = true;
7189         R_RenderScene();
7190         r_waterstate.numwaterplanes = 0;
7191
7192         R_ResetViewRendering2D();
7193
7194         R_Bloom_CopyHDRTexture();
7195         R_Bloom_MakeTexture();
7196
7197         // restore the view settings
7198         r_refdef.view.width = oldwidth;
7199         r_refdef.view.height = oldheight;
7200         r_refdef.view.colorscale = oldcolorscale;
7201         r_frame++; // used only by R_GetCurrentTexture
7202
7203         R_ResetViewRendering3D();
7204
7205         R_ClearScreen(r_refdef.fogenabled);
7206         if (r_timereport_active)
7207                 R_TimeReport("viewclear");
7208 }
7209
7210 static void R_BlendView(void)
7211 {
7212         unsigned int permutation;
7213         float uservecs[4][4];
7214
7215         switch (vid.renderpath)
7216         {
7217         case RENDERPATH_GL20:
7218         case RENDERPATH_CGGL:
7219                 permutation =
7220                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
7221                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
7222                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
7223                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
7224                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
7225
7226                 if (r_bloomstate.texture_screen)
7227                 {
7228                         // make sure the buffer is available
7229                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
7230
7231                         R_ResetViewRendering2D();
7232                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7233                         R_Mesh_ColorPointer(NULL, 0, 0);
7234
7235                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
7236                         {
7237                                 // declare variables
7238                                 float speed;
7239                                 static float avgspeed;
7240
7241                                 speed = VectorLength(cl.movement_velocity);
7242
7243                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
7244                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
7245
7246                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
7247                                 speed = bound(0, speed, 1);
7248                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
7249
7250                                 // calculate values into a standard alpha
7251                                 cl.motionbluralpha = 1 - exp(-
7252                                                 (
7253                                                  (r_motionblur.value * speed / 80)
7254                                                  +
7255                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
7256                                                 )
7257                                                 /
7258                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
7259                                            );
7260
7261                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
7262                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
7263                                 // apply the blur
7264                                 if (cl.motionbluralpha > 0)
7265                                 {
7266                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7267                                         GL_Color(1, 1, 1, cl.motionbluralpha);
7268                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7269                                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7270                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7271                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7272                                 }
7273                         }
7274
7275                         // copy view into the screen texture
7276                         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);
7277                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7278                 }
7279                 else if (!r_bloomstate.texture_bloom)
7280                 {
7281                         // we may still have to do view tint...
7282                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7283                         {
7284                                 // apply a color tint to the whole view
7285                                 R_ResetViewRendering2D();
7286                                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7287                                 R_Mesh_ColorPointer(NULL, 0, 0);
7288                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7289                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7290                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7291                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7292                         }
7293                         break; // no screen processing, no bloom, skip it
7294                 }
7295
7296                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
7297                 {
7298                         // render simple bloom effect
7299                         // copy the screen and shrink it and darken it for the bloom process
7300                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
7301                         // make the bloom texture
7302                         R_Bloom_MakeTexture();
7303                 }
7304
7305 #if _MSC_VER >= 1400
7306 #define sscanf sscanf_s
7307 #endif
7308                 memset(uservecs, 0, sizeof(uservecs));
7309                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
7310                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
7311                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
7312                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
7313
7314                 R_ResetViewRendering2D();
7315                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7316                 R_Mesh_ColorPointer(NULL, 0, 0);
7317                 GL_Color(1, 1, 1, 1);
7318                 GL_BlendFunc(GL_ONE, GL_ZERO);
7319                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7320                 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7321
7322                 switch(vid.renderpath)
7323                 {
7324                 case RENDERPATH_GL20:
7325                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
7326                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
7327                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
7328                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
7329                         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]);
7330                         if (r_glsl_permutation->loc_ClientTime         >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime        , cl.time);
7331                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
7332                         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]);
7333                         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]);
7334                         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]);
7335                         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]);
7336                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
7337                         break;
7338                 case RENDERPATH_CGGL:
7339 #ifdef SUPPORTCG
7340                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
7341                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
7342                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
7343                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
7344                         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
7345                         if (r_cg_permutation->fp_ClientTime        ) cgGLSetParameter1f(     r_cg_permutation->fp_ClientTime        , cl.time);CHECKCGERROR
7346                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
7347                         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
7348                         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
7349                         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
7350                         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
7351                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
7352 #endif
7353                         break;
7354                 default:
7355                         break;
7356                 }
7357                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7358                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7359                 break;
7360         case RENDERPATH_GL13:
7361         case RENDERPATH_GL11:
7362                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7363                 {
7364                         // apply a color tint to the whole view
7365                         R_ResetViewRendering2D();
7366                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7367                         R_Mesh_ColorPointer(NULL, 0, 0);
7368                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7369                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7370                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7371                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7372                 }
7373                 break;
7374         }
7375 }
7376
7377 matrix4x4_t r_waterscrollmatrix;
7378
7379 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
7380 {
7381         if (r_refdef.fog_density)
7382         {
7383                 r_refdef.fogcolor[0] = r_refdef.fog_red;
7384                 r_refdef.fogcolor[1] = r_refdef.fog_green;
7385                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7386
7387                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7388                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7389                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7390                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7391
7392                 {
7393                         vec3_t fogvec;
7394                         VectorCopy(r_refdef.fogcolor, fogvec);
7395                         //   color.rgb *= ContrastBoost * SceneBrightness;
7396                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7397                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7398                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7399                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7400                 }
7401         }
7402 }
7403
7404 void R_UpdateVariables(void)
7405 {
7406         R_Textures_Frame();
7407
7408         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7409
7410         r_refdef.farclip = r_farclip_base.value;
7411         if (r_refdef.scene.worldmodel)
7412                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7413         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7414
7415         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7416                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7417         r_refdef.polygonfactor = 0;
7418         r_refdef.polygonoffset = 0;
7419         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7420         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7421
7422         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7423         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7424         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
7425         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7426         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7427         if (r_showsurfaces.integer)
7428         {
7429                 r_refdef.scene.rtworld = false;
7430                 r_refdef.scene.rtworldshadows = false;
7431                 r_refdef.scene.rtdlight = false;
7432                 r_refdef.scene.rtdlightshadows = false;
7433                 r_refdef.lightmapintensity = 0;
7434         }
7435
7436         if (gamemode == GAME_NEHAHRA)
7437         {
7438                 if (gl_fogenable.integer)
7439                 {
7440                         r_refdef.oldgl_fogenable = true;
7441                         r_refdef.fog_density = gl_fogdensity.value;
7442                         r_refdef.fog_red = gl_fogred.value;
7443                         r_refdef.fog_green = gl_foggreen.value;
7444                         r_refdef.fog_blue = gl_fogblue.value;
7445                         r_refdef.fog_alpha = 1;
7446                         r_refdef.fog_start = 0;
7447                         r_refdef.fog_end = gl_skyclip.value;
7448                         r_refdef.fog_height = 1<<30;
7449                         r_refdef.fog_fadedepth = 128;
7450                 }
7451                 else if (r_refdef.oldgl_fogenable)
7452                 {
7453                         r_refdef.oldgl_fogenable = false;
7454                         r_refdef.fog_density = 0;
7455                         r_refdef.fog_red = 0;
7456                         r_refdef.fog_green = 0;
7457                         r_refdef.fog_blue = 0;
7458                         r_refdef.fog_alpha = 0;
7459                         r_refdef.fog_start = 0;
7460                         r_refdef.fog_end = 0;
7461                         r_refdef.fog_height = 1<<30;
7462                         r_refdef.fog_fadedepth = 128;
7463                 }
7464         }
7465
7466         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7467         r_refdef.fog_start = max(0, r_refdef.fog_start);
7468         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7469
7470         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
7471
7472         if (r_refdef.fog_density && r_drawfog.integer)
7473         {
7474                 r_refdef.fogenabled = true;
7475                 // this is the point where the fog reaches 0.9986 alpha, which we
7476                 // consider a good enough cutoff point for the texture
7477                 // (0.9986 * 256 == 255.6)
7478                 if (r_fog_exp2.integer)
7479                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7480                 else
7481                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7482                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7483                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7484                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7485                 // fog color was already set
7486                 // update the fog texture
7487                 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)
7488                         R_BuildFogTexture();
7489         }
7490         else
7491                 r_refdef.fogenabled = false;
7492
7493         switch(vid.renderpath)
7494         {
7495         case RENDERPATH_GL20:
7496         case RENDERPATH_CGGL:
7497                 if(v_glslgamma.integer && !vid_gammatables_trivial)
7498                 {
7499                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7500                         {
7501                                 // build GLSL gamma texture
7502 #define RAMPWIDTH 256
7503                                 unsigned short ramp[RAMPWIDTH * 3];
7504                                 unsigned char rampbgr[RAMPWIDTH][4];
7505                                 int i;
7506
7507                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7508
7509                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7510                                 for(i = 0; i < RAMPWIDTH; ++i)
7511                                 {
7512                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7513                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7514                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7515                                         rampbgr[i][3] = 0;
7516                                 }
7517                                 if (r_texture_gammaramps)
7518                                 {
7519                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
7520                                 }
7521                                 else
7522                                 {
7523                                         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);
7524                                 }
7525                         }
7526                 }
7527                 else
7528                 {
7529                         // remove GLSL gamma texture
7530                 }
7531                 break;
7532         case RENDERPATH_GL13:
7533         case RENDERPATH_GL11:
7534                 break;
7535         }
7536 }
7537
7538 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7539 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7540 /*
7541 ================
7542 R_SelectScene
7543 ================
7544 */
7545 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7546         if( scenetype != r_currentscenetype ) {
7547                 // store the old scenetype
7548                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7549                 r_currentscenetype = scenetype;
7550                 // move in the new scene
7551                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7552         }
7553 }
7554
7555 /*
7556 ================
7557 R_GetScenePointer
7558 ================
7559 */
7560 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7561 {
7562         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7563         if( scenetype == r_currentscenetype ) {
7564                 return &r_refdef.scene;
7565         } else {
7566                 return &r_scenes_store[ scenetype ];
7567         }
7568 }
7569
7570 /*
7571 ================
7572 R_RenderView
7573 ================
7574 */
7575 void R_RenderView(void)
7576 {
7577         if (r_timereport_active)
7578                 R_TimeReport("start");
7579         r_frame++; // used only by R_GetCurrentTexture
7580         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7581
7582         if (!r_drawentities.integer)
7583                 r_refdef.scene.numentities = 0;
7584
7585         R_AnimCache_ClearCache();
7586         R_FrameData_NewFrame();
7587
7588         if (r_refdef.view.isoverlay)
7589         {
7590                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7591                 GL_Clear( GL_DEPTH_BUFFER_BIT );
7592                 R_TimeReport("depthclear");
7593
7594                 r_refdef.view.showdebug = false;
7595
7596                 r_waterstate.enabled = false;
7597                 r_waterstate.numwaterplanes = 0;
7598
7599                 R_RenderScene();
7600
7601                 CHECKGLERROR
7602                 return;
7603         }
7604
7605         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
7606                 return; //Host_Error ("R_RenderView: NULL worldmodel");
7607
7608         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
7609
7610         // break apart the view matrix into vectors for various purposes
7611         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
7612         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
7613         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
7614         VectorNegate(r_refdef.view.left, r_refdef.view.right);
7615         // make an inverted copy of the view matrix for tracking sprites
7616         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
7617
7618         R_Shadow_UpdateWorldLightSelection();
7619
7620         R_Bloom_StartFrame();
7621         R_Water_StartFrame();
7622
7623         CHECKGLERROR
7624         if (r_timereport_active)
7625                 R_TimeReport("viewsetup");
7626
7627         R_ResetViewRendering3D();
7628
7629         if (r_refdef.view.clear || r_refdef.fogenabled)
7630         {
7631                 R_ClearScreen(r_refdef.fogenabled);
7632                 if (r_timereport_active)
7633                         R_TimeReport("viewclear");
7634         }
7635         r_refdef.view.clear = true;
7636
7637         // this produces a bloom texture to be used in R_BlendView() later
7638         if (r_hdr.integer && r_bloomstate.bloomwidth)
7639                 R_HDR_RenderBloomTexture();
7640
7641         r_refdef.view.showdebug = true;
7642
7643         R_View_Update();
7644         if (r_timereport_active)
7645                 R_TimeReport("visibility");
7646
7647         r_waterstate.numwaterplanes = 0;
7648         if (r_waterstate.enabled)
7649                 R_RenderWaterPlanes();
7650
7651         R_RenderScene();
7652         r_waterstate.numwaterplanes = 0;
7653
7654         R_BlendView();
7655         if (r_timereport_active)
7656                 R_TimeReport("blendview");
7657
7658         GL_Scissor(0, 0, vid.width, vid.height);
7659         GL_ScissorTest(false);
7660         CHECKGLERROR
7661 }
7662
7663 void R_RenderWaterPlanes(void)
7664 {
7665         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7666         {
7667                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7668                 if (r_timereport_active)
7669                         R_TimeReport("waterworld");
7670         }
7671
7672         // don't let sound skip if going slow
7673         if (r_refdef.scene.extraupdate)
7674                 S_ExtraUpdate ();
7675
7676         R_DrawModelsAddWaterPlanes();
7677         if (r_timereport_active)
7678                 R_TimeReport("watermodels");
7679
7680         if (r_waterstate.numwaterplanes)
7681         {
7682                 R_Water_ProcessPlanes();
7683                 if (r_timereport_active)
7684                         R_TimeReport("waterscenes");
7685         }
7686 }
7687
7688 extern void R_DrawLightningBeams (void);
7689 extern void VM_CL_AddPolygonsToMeshQueue (void);
7690 extern void R_DrawPortals (void);
7691 extern cvar_t cl_locs_show;
7692 static void R_DrawLocs(void);
7693 static void R_DrawEntityBBoxes(void);
7694 static void R_DrawModelDecals(void);
7695 extern cvar_t cl_decals_newsystem;
7696 extern qboolean r_shadow_usingdeferredprepass;
7697 void R_RenderScene(void)
7698 {
7699         r_refdef.stats.renders++;
7700
7701         R_UpdateFogColor();
7702
7703         // don't let sound skip if going slow
7704         if (r_refdef.scene.extraupdate)
7705                 S_ExtraUpdate ();
7706
7707         R_MeshQueue_BeginScene();
7708
7709         R_SkyStartFrame();
7710
7711         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);
7712
7713         if (cl.csqc_vidvars.drawworld)
7714         {
7715                 // don't let sound skip if going slow
7716                 if (r_refdef.scene.extraupdate)
7717                         S_ExtraUpdate ();
7718
7719                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7720                 {
7721                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7722                         if (r_timereport_active)
7723                                 R_TimeReport("worldsky");
7724                 }
7725
7726                 if (R_DrawBrushModelsSky() && r_timereport_active)
7727                         R_TimeReport("bmodelsky");
7728
7729                 if (skyrendermasked && skyrenderlater)
7730                 {
7731                         // we have to force off the water clipping plane while rendering sky
7732                         R_SetupView(false);
7733                         R_Sky();
7734                         R_SetupView(true);
7735                         if (r_timereport_active)
7736                                 R_TimeReport("sky");
7737                 }
7738         }
7739
7740         R_AnimCache_CacheVisibleEntities();
7741         if (r_timereport_active)
7742                 R_TimeReport("animation");
7743
7744         R_Shadow_PrepareLights();
7745         if (r_timereport_active)
7746                 R_TimeReport("preparelights");
7747
7748         if (r_shadow_usingdeferredprepass)
7749                 R_Shadow_DrawPrepass();
7750
7751         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7752         {
7753                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7754                 if (r_timereport_active)
7755                         R_TimeReport("worlddepth");
7756         }
7757         if (r_depthfirst.integer >= 2)
7758         {
7759                 R_DrawModelsDepth();
7760                 if (r_timereport_active)
7761                         R_TimeReport("modeldepth");
7762         }
7763
7764         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7765         {
7766                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7767                 if (r_timereport_active)
7768                         R_TimeReport("world");
7769         }
7770
7771         // don't let sound skip if going slow
7772         if (r_refdef.scene.extraupdate)
7773                 S_ExtraUpdate ();
7774
7775         R_DrawModels();
7776         if (r_timereport_active)
7777                 R_TimeReport("models");
7778
7779         // don't let sound skip if going slow
7780         if (r_refdef.scene.extraupdate)
7781                 S_ExtraUpdate ();
7782
7783         if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7784         {
7785                 R_DrawModelShadows();
7786                 R_ResetViewRendering3D();
7787                 // don't let sound skip if going slow
7788                 if (r_refdef.scene.extraupdate)
7789                         S_ExtraUpdate ();
7790         }
7791
7792         if (!r_shadow_usingdeferredprepass)
7793         {
7794                 R_Shadow_DrawLights();
7795                 if (r_timereport_active)
7796                         R_TimeReport("rtlights");
7797         }
7798
7799         // don't let sound skip if going slow
7800         if (r_refdef.scene.extraupdate)
7801                 S_ExtraUpdate ();
7802
7803         if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7804         {
7805                 R_DrawModelShadows();
7806                 R_ResetViewRendering3D();
7807                 // don't let sound skip if going slow
7808                 if (r_refdef.scene.extraupdate)
7809                         S_ExtraUpdate ();
7810         }
7811
7812         if (cl.csqc_vidvars.drawworld)
7813         {
7814                 if (cl_decals_newsystem.integer)
7815                 {
7816                         R_DrawModelDecals();
7817                         if (r_timereport_active)
7818                                 R_TimeReport("modeldecals");
7819                 }
7820                 else
7821                 {
7822                         R_DrawDecals();
7823                         if (r_timereport_active)
7824                                 R_TimeReport("decals");
7825                 }
7826
7827                 R_DrawParticles();
7828                 if (r_timereport_active)
7829                         R_TimeReport("particles");
7830
7831                 R_DrawExplosions();
7832                 if (r_timereport_active)
7833                         R_TimeReport("explosions");
7834
7835                 R_DrawLightningBeams();
7836                 if (r_timereport_active)
7837                         R_TimeReport("lightning");
7838         }
7839
7840         VM_CL_AddPolygonsToMeshQueue();
7841
7842         if (r_refdef.view.showdebug)
7843         {
7844                 if (cl_locs_show.integer)
7845                 {
7846                         R_DrawLocs();
7847                         if (r_timereport_active)
7848                                 R_TimeReport("showlocs");
7849                 }
7850
7851                 if (r_drawportals.integer)
7852                 {
7853                         R_DrawPortals();
7854                         if (r_timereport_active)
7855                                 R_TimeReport("portals");
7856                 }
7857
7858                 if (r_showbboxes.value > 0)
7859                 {
7860                         R_DrawEntityBBoxes();
7861                         if (r_timereport_active)
7862                                 R_TimeReport("bboxes");
7863                 }
7864         }
7865
7866         R_MeshQueue_RenderTransparent();
7867         if (r_timereport_active)
7868                 R_TimeReport("drawtrans");
7869
7870         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))
7871         {
7872                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7873                 if (r_timereport_active)
7874                         R_TimeReport("worlddebug");
7875                 R_DrawModelsDebug();
7876                 if (r_timereport_active)
7877                         R_TimeReport("modeldebug");
7878         }
7879
7880         if (cl.csqc_vidvars.drawworld)
7881         {
7882                 R_Shadow_DrawCoronas();
7883                 if (r_timereport_active)
7884                         R_TimeReport("coronas");
7885         }
7886
7887         // don't let sound skip if going slow
7888         if (r_refdef.scene.extraupdate)
7889                 S_ExtraUpdate ();
7890
7891         R_ResetViewRendering2D();
7892 }
7893
7894 static const unsigned short bboxelements[36] =
7895 {
7896         5, 1, 3, 5, 3, 7,
7897         6, 2, 0, 6, 0, 4,
7898         7, 3, 2, 7, 2, 6,
7899         4, 0, 1, 4, 1, 5,
7900         4, 5, 7, 4, 7, 6,
7901         1, 0, 2, 1, 2, 3,
7902 };
7903
7904 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7905 {
7906         int i;
7907         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7908
7909         RSurf_ActiveWorldEntity();
7910
7911         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7912         GL_DepthMask(false);
7913         GL_DepthRange(0, 1);
7914         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7915         R_Mesh_ResetTextureState();
7916
7917         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7918         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7919         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7920         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7921         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7922         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7923         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7924         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7925         R_FillColors(color4f, 8, cr, cg, cb, ca);
7926         if (r_refdef.fogenabled)
7927         {
7928                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7929                 {
7930                         f1 = RSurf_FogVertex(v);
7931                         f2 = 1 - f1;
7932                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7933                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7934                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7935                 }
7936         }
7937         R_Mesh_VertexPointer(vertex3f, 0, 0);
7938         R_Mesh_ColorPointer(color4f, 0, 0);
7939         R_Mesh_ResetTextureState();
7940         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7941         R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
7942 }
7943
7944 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7945 {
7946         int i;
7947         float color[4];
7948         prvm_edict_t *edict;
7949         prvm_prog_t *prog_save = prog;
7950
7951         // this function draws bounding boxes of server entities
7952         if (!sv.active)
7953                 return;
7954
7955         GL_CullFace(GL_NONE);
7956         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7957
7958         prog = 0;
7959         SV_VM_Begin();
7960         for (i = 0;i < numsurfaces;i++)
7961         {
7962                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7963                 switch ((int)edict->fields.server->solid)
7964                 {
7965                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7966                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7967                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7968                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7969                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7970                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7971                 }
7972                 color[3] *= r_showbboxes.value;
7973                 color[3] = bound(0, color[3], 1);
7974                 GL_DepthTest(!r_showdisabledepthtest.integer);
7975                 GL_CullFace(r_refdef.view.cullface_front);
7976                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7977         }
7978         SV_VM_End();
7979         prog = prog_save;
7980 }
7981
7982 static void R_DrawEntityBBoxes(void)
7983 {
7984         int i;
7985         prvm_edict_t *edict;
7986         vec3_t center;
7987         prvm_prog_t *prog_save = prog;
7988
7989         // this function draws bounding boxes of server entities
7990         if (!sv.active)
7991                 return;
7992
7993         prog = 0;
7994         SV_VM_Begin();
7995         for (i = 0;i < prog->num_edicts;i++)
7996         {
7997                 edict = PRVM_EDICT_NUM(i);
7998                 if (edict->priv.server->free)
7999                         continue;
8000                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
8001                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
8002                         continue;
8003                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
8004                         continue;
8005                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
8006                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
8007         }
8008         SV_VM_End();
8009         prog = prog_save;
8010 }
8011
8012 static const int nomodelelement3i[24] =
8013 {
8014         5, 2, 0,
8015         5, 1, 2,
8016         5, 0, 3,
8017         5, 3, 1,
8018         0, 2, 4,
8019         2, 1, 4,
8020         3, 0, 4,
8021         1, 3, 4
8022 };
8023
8024 static const unsigned short nomodelelement3s[24] =
8025 {
8026         5, 2, 0,
8027         5, 1, 2,
8028         5, 0, 3,
8029         5, 3, 1,
8030         0, 2, 4,
8031         2, 1, 4,
8032         3, 0, 4,
8033         1, 3, 4
8034 };
8035
8036 static const float nomodelvertex3f[6*3] =
8037 {
8038         -16,   0,   0,
8039          16,   0,   0,
8040           0, -16,   0,
8041           0,  16,   0,
8042           0,   0, -16,
8043           0,   0,  16
8044 };
8045
8046 static const float nomodelcolor4f[6*4] =
8047 {
8048         0.0f, 0.0f, 0.5f, 1.0f,
8049         0.0f, 0.0f, 0.5f, 1.0f,
8050         0.0f, 0.5f, 0.0f, 1.0f,
8051         0.0f, 0.5f, 0.0f, 1.0f,
8052         0.5f, 0.0f, 0.0f, 1.0f,
8053         0.5f, 0.0f, 0.0f, 1.0f
8054 };
8055
8056 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8057 {
8058         int i;
8059         float f1, f2, *c;
8060         float color4f[6*4];
8061
8062         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);
8063
8064         // this is only called once per entity so numsurfaces is always 1, and
8065         // surfacelist is always {0}, so this code does not handle batches
8066
8067         if (rsurface.ent_flags & RENDER_ADDITIVE)
8068         {
8069                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
8070                 GL_DepthMask(false);
8071         }
8072         else if (rsurface.colormod[3] < 1)
8073         {
8074                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8075                 GL_DepthMask(false);
8076         }
8077         else
8078         {
8079                 GL_BlendFunc(GL_ONE, GL_ZERO);
8080                 GL_DepthMask(true);
8081         }
8082         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8083         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8084         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8085         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8086         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8087         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
8088         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8089         R_Mesh_ColorPointer(color4f, 0, 0);
8090         for (i = 0, c = color4f;i < 6;i++, c += 4)
8091         {
8092                 c[0] *= rsurface.colormod[0];
8093                 c[1] *= rsurface.colormod[1];
8094                 c[2] *= rsurface.colormod[2];
8095                 c[3] *= rsurface.colormod[3];
8096         }
8097         if (r_refdef.fogenabled)
8098         {
8099                 for (i = 0, c = color4f;i < 6;i++, c += 4)
8100                 {
8101                         f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
8102                         f2 = 1 - f1;
8103                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8104                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8105                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8106                 }
8107         }
8108         R_Mesh_ResetTextureState();
8109         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
8110 }
8111
8112 void R_DrawNoModel(entity_render_t *ent)
8113 {
8114         vec3_t org;
8115         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8116         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8117                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8118         else
8119                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8120 }
8121
8122 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8123 {
8124         vec3_t right1, right2, diff, normal;
8125
8126         VectorSubtract (org2, org1, normal);
8127
8128         // calculate 'right' vector for start
8129         VectorSubtract (r_refdef.view.origin, org1, diff);
8130         CrossProduct (normal, diff, right1);
8131         VectorNormalize (right1);
8132
8133         // calculate 'right' vector for end
8134         VectorSubtract (r_refdef.view.origin, org2, diff);
8135         CrossProduct (normal, diff, right2);
8136         VectorNormalize (right2);
8137
8138         vert[ 0] = org1[0] + width * right1[0];
8139         vert[ 1] = org1[1] + width * right1[1];
8140         vert[ 2] = org1[2] + width * right1[2];
8141         vert[ 3] = org1[0] - width * right1[0];
8142         vert[ 4] = org1[1] - width * right1[1];
8143         vert[ 5] = org1[2] - width * right1[2];
8144         vert[ 6] = org2[0] - width * right2[0];
8145         vert[ 7] = org2[1] - width * right2[1];
8146         vert[ 8] = org2[2] - width * right2[2];
8147         vert[ 9] = org2[0] + width * right2[0];
8148         vert[10] = org2[1] + width * right2[1];
8149         vert[11] = org2[2] + width * right2[2];
8150 }
8151
8152 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)
8153 {
8154         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8155         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8156         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8157         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8158         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8159         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8160         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8161         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8162         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8163         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8164         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8165         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8166 }
8167
8168 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8169 {
8170         int i;
8171         float *vertex3f;
8172         float v[3];
8173         VectorSet(v, x, y, z);
8174         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8175                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8176                         break;
8177         if (i == mesh->numvertices)
8178         {
8179                 if (mesh->numvertices < mesh->maxvertices)
8180                 {
8181                         VectorCopy(v, vertex3f);
8182                         mesh->numvertices++;
8183                 }
8184                 return mesh->numvertices;
8185         }
8186         else
8187                 return i;
8188 }
8189
8190 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8191 {
8192         int i;
8193         int *e, element[3];
8194         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8195         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8196         e = mesh->element3i + mesh->numtriangles * 3;
8197         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8198         {
8199                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8200                 if (mesh->numtriangles < mesh->maxtriangles)
8201                 {
8202                         *e++ = element[0];
8203                         *e++ = element[1];
8204                         *e++ = element[2];
8205                         mesh->numtriangles++;
8206                 }
8207                 element[1] = element[2];
8208         }
8209 }
8210
8211 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8212 {
8213         int i;
8214         int *e, element[3];
8215         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8216         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8217         e = mesh->element3i + mesh->numtriangles * 3;
8218         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8219         {
8220                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8221                 if (mesh->numtriangles < mesh->maxtriangles)
8222                 {
8223                         *e++ = element[0];
8224                         *e++ = element[1];
8225                         *e++ = element[2];
8226                         mesh->numtriangles++;
8227                 }
8228                 element[1] = element[2];
8229         }
8230 }
8231
8232 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8233 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8234 {
8235         int planenum, planenum2;
8236         int w;
8237         int tempnumpoints;
8238         mplane_t *plane, *plane2;
8239         double maxdist;
8240         double temppoints[2][256*3];
8241         // figure out how large a bounding box we need to properly compute this brush
8242         maxdist = 0;
8243         for (w = 0;w < numplanes;w++)
8244                 maxdist = max(maxdist, fabs(planes[w].dist));
8245         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8246         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8247         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8248         {
8249                 w = 0;
8250                 tempnumpoints = 4;
8251                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8252                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8253                 {
8254                         if (planenum2 == planenum)
8255                                 continue;
8256                         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);
8257                         w = !w;
8258                 }
8259                 if (tempnumpoints < 3)
8260                         continue;
8261                 // generate elements forming a triangle fan for this polygon
8262                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8263         }
8264 }
8265
8266 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)
8267 {
8268         texturelayer_t *layer;
8269         layer = t->currentlayers + t->currentnumlayers++;
8270         layer->type = type;
8271         layer->depthmask = depthmask;
8272         layer->blendfunc1 = blendfunc1;
8273         layer->blendfunc2 = blendfunc2;
8274         layer->texture = texture;
8275         layer->texmatrix = *matrix;
8276         layer->color[0] = r;
8277         layer->color[1] = g;
8278         layer->color[2] = b;
8279         layer->color[3] = a;
8280 }
8281
8282 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8283 {
8284         double index, f;
8285         index = parms[2] + r_refdef.scene.time * parms[3];
8286         index -= floor(index);
8287         switch (func)
8288         {
8289         default:
8290         case Q3WAVEFUNC_NONE:
8291         case Q3WAVEFUNC_NOISE:
8292         case Q3WAVEFUNC_COUNT:
8293                 f = 0;
8294                 break;
8295         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8296         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8297         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8298         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8299         case Q3WAVEFUNC_TRIANGLE:
8300                 index *= 4;
8301                 f = index - floor(index);
8302                 if (index < 1)
8303                         f = f;
8304                 else if (index < 2)
8305                         f = 1 - f;
8306                 else if (index < 3)
8307                         f = -f;
8308                 else
8309                         f = -(1 - f);
8310                 break;
8311         }
8312         return (float)(parms[0] + parms[1] * f);
8313 }
8314
8315 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8316 {
8317         int w, h, idx;
8318         float f;
8319         float tcmat[12];
8320         matrix4x4_t matrix, temp;
8321         switch(tcmod->tcmod)
8322         {
8323                 case Q3TCMOD_COUNT:
8324                 case Q3TCMOD_NONE:
8325                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8326                                 matrix = r_waterscrollmatrix;
8327                         else
8328                                 matrix = identitymatrix;
8329                         break;
8330                 case Q3TCMOD_ENTITYTRANSLATE:
8331                         // this is used in Q3 to allow the gamecode to control texcoord
8332                         // scrolling on the entity, which is not supported in darkplaces yet.
8333                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8334                         break;
8335                 case Q3TCMOD_ROTATE:
8336                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8337                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
8338                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8339                         break;
8340                 case Q3TCMOD_SCALE:
8341                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8342                         break;
8343                 case Q3TCMOD_SCROLL:
8344                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
8345                         break;
8346                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8347                         w = (int) tcmod->parms[0];
8348                         h = (int) tcmod->parms[1];
8349                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
8350                         f = f - floor(f);
8351                         idx = (int) floor(f * w * h);
8352                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8353                         break;
8354                 case Q3TCMOD_STRETCH:
8355                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8356                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8357                         break;
8358                 case Q3TCMOD_TRANSFORM:
8359                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8360                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8361                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8362                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8363                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8364                         break;
8365                 case Q3TCMOD_TURBULENT:
8366                         // this is handled in the RSurf_PrepareVertices function
8367                         matrix = identitymatrix;
8368                         break;
8369         }
8370         temp = *texmatrix;
8371         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8372 }
8373
8374 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8375 {
8376         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
8377         char name[MAX_QPATH];
8378         skinframe_t *skinframe;
8379         unsigned char pixels[296*194];
8380         strlcpy(cache->name, skinname, sizeof(cache->name));
8381         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8382         if (developer_loading.integer)
8383                 Con_Printf("loading %s\n", name);
8384         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8385         if (!skinframe || !skinframe->base)
8386         {
8387                 unsigned char *f;
8388                 fs_offset_t filesize;
8389                 skinframe = NULL;
8390                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8391                 if (f)
8392                 {
8393                         if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
8394                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8395                         Mem_Free(f);
8396                 }
8397         }
8398         cache->skinframe = skinframe;
8399 }
8400
8401 texture_t *R_GetCurrentTexture(texture_t *t)
8402 {
8403         int i;
8404         const entity_render_t *ent = rsurface.entity;
8405         dp_model_t *model = ent->model;
8406         q3shaderinfo_layer_tcmod_t *tcmod;
8407
8408         if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
8409                 return t->currentframe;
8410         t->update_lastrenderframe = r_frame;
8411         t->update_lastrenderentity = (void *)ent;
8412
8413         // switch to an alternate material if this is a q1bsp animated material
8414         {
8415                 texture_t *texture = t;
8416                 int s = rsurface.ent_skinnum;
8417                 if ((unsigned int)s >= (unsigned int)model->numskins)
8418                         s = 0;
8419                 if (model->skinscenes)
8420                 {
8421                         if (model->skinscenes[s].framecount > 1)
8422                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8423                         else
8424                                 s = model->skinscenes[s].firstframe;
8425                 }
8426                 if (s > 0)
8427                         t = t + s * model->num_surfaces;
8428                 if (t->animated)
8429                 {
8430                         // use an alternate animation if the entity's frame is not 0,
8431                         // and only if the texture has an alternate animation
8432                         if (rsurface.ent_alttextures && t->anim_total[1])
8433                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
8434                         else
8435                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
8436                 }
8437                 texture->currentframe = t;
8438         }
8439
8440         // update currentskinframe to be a qw skin or animation frame
8441         if (rsurface.ent_qwskin >= 0)
8442         {
8443                 i = rsurface.ent_qwskin;
8444                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8445                 {
8446                         r_qwskincache_size = cl.maxclients;
8447                         if (r_qwskincache)
8448                                 Mem_Free(r_qwskincache);
8449                         r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8450                 }
8451                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8452                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8453                 t->currentskinframe = r_qwskincache[i].skinframe;
8454                 if (t->currentskinframe == NULL)
8455                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8456         }
8457         else if (t->numskinframes >= 2)
8458                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8459         if (t->backgroundnumskinframes >= 2)
8460                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
8461
8462         t->currentmaterialflags = t->basematerialflags;
8463         t->currentalpha = rsurface.colormod[3];
8464         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
8465                 t->currentalpha *= r_wateralpha.value;
8466         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
8467                 t->currentalpha *= t->r_water_wateralpha;
8468         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
8469                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
8470         if (!(rsurface.ent_flags & RENDER_LIGHT))
8471                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8472         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8473         {
8474                 // pick a model lighting mode
8475                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8476                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8477                 else
8478                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8479         }
8480         if (rsurface.ent_flags & RENDER_ADDITIVE)
8481                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8482         else if (t->currentalpha < 1)
8483                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8484         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8485                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8486         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8487                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8488         if (t->backgroundnumskinframes)
8489                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8490         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8491         {
8492                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
8493                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8494         }
8495         else
8496                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
8497         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8498                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8499
8500         // there is no tcmod
8501         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8502         {
8503                 t->currenttexmatrix = r_waterscrollmatrix;
8504                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8505         }
8506         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8507         {
8508                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8509                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8510         }
8511
8512         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8513                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8514         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8515                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8516
8517         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8518         if (t->currentskinframe->qpixels)
8519                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8520         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8521         if (!t->basetexture)
8522                 t->basetexture = r_texture_notexture;
8523         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8524         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8525         t->nmaptexture = t->currentskinframe->nmap;
8526         if (!t->nmaptexture)
8527                 t->nmaptexture = r_texture_blanknormalmap;
8528         t->glosstexture = r_texture_black;
8529         t->glowtexture = t->currentskinframe->glow;
8530         t->fogtexture = t->currentskinframe->fog;
8531         if (t->backgroundnumskinframes)
8532         {
8533                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8534                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8535                 t->backgroundglosstexture = r_texture_black;
8536                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8537                 if (!t->backgroundnmaptexture)
8538                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8539         }
8540         else
8541         {
8542                 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
8543                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8544                 t->backgroundglosstexture = r_texture_black;
8545                 t->backgroundglowtexture = NULL;
8546         }
8547         t->specularpower = r_shadow_glossexponent.value;
8548         // TODO: store reference values for these in the texture?
8549         t->specularscale = 0;
8550         if (r_shadow_gloss.integer > 0)
8551         {
8552                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8553                 {
8554                         if (r_shadow_glossintensity.value > 0)
8555                         {
8556                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8557                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8558                                 t->specularscale = r_shadow_glossintensity.value;
8559                         }
8560                 }
8561                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8562                 {
8563                         t->glosstexture = r_texture_white;
8564                         t->backgroundglosstexture = r_texture_white;
8565                         t->specularscale = r_shadow_gloss2intensity.value;
8566                         t->specularpower = r_shadow_gloss2exponent.value;
8567                 }
8568         }
8569         t->specularscale *= t->specularscalemod;
8570         t->specularpower *= t->specularpowermod;
8571
8572         // lightmaps mode looks bad with dlights using actual texturing, so turn
8573         // off the colormap and glossmap, but leave the normalmap on as it still
8574         // accurately represents the shading involved
8575         if (gl_lightmaps.integer)
8576         {
8577                 t->basetexture = r_texture_grey128;
8578                 t->pantstexture = r_texture_black;
8579                 t->shirttexture = r_texture_black;
8580                 t->nmaptexture = r_texture_blanknormalmap;
8581                 t->glosstexture = r_texture_black;
8582                 t->glowtexture = NULL;
8583                 t->fogtexture = NULL;
8584                 t->backgroundbasetexture = NULL;
8585                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8586                 t->backgroundglosstexture = r_texture_black;
8587                 t->backgroundglowtexture = NULL;
8588                 t->specularscale = 0;
8589                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8590         }
8591
8592         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8593         VectorClear(t->dlightcolor);
8594         t->currentnumlayers = 0;
8595         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8596         {
8597                 int blendfunc1, blendfunc2;
8598                 qboolean depthmask;
8599                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8600                 {
8601                         blendfunc1 = GL_SRC_ALPHA;
8602                         blendfunc2 = GL_ONE;
8603                 }
8604                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8605                 {
8606                         blendfunc1 = GL_SRC_ALPHA;
8607                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8608                 }
8609                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8610                 {
8611                         blendfunc1 = t->customblendfunc[0];
8612                         blendfunc2 = t->customblendfunc[1];
8613                 }
8614                 else
8615                 {
8616                         blendfunc1 = GL_ONE;
8617                         blendfunc2 = GL_ZERO;
8618                 }
8619                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8620                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8621                 {
8622                         // fullbright is not affected by r_refdef.lightmapintensity
8623                         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]);
8624                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8625                                 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]);
8626                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8627                                 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]);
8628                 }
8629                 else
8630                 {
8631                         vec3_t ambientcolor;
8632                         float colorscale;
8633                         // set the color tint used for lights affecting this surface
8634                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8635                         colorscale = 2;
8636                         // q3bsp has no lightmap updates, so the lightstylevalue that
8637                         // would normally be baked into the lightmap must be
8638                         // applied to the color
8639                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8640                         if (model->type == mod_brushq3)
8641                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8642                         colorscale *= r_refdef.lightmapintensity;
8643                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8644                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8645                         // basic lit geometry
8646                         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]);
8647                         // add pants/shirt if needed
8648                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8649                                 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]);
8650                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8651                                 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]);
8652                         // now add ambient passes if needed
8653                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8654                         {
8655                                 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]);
8656                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8657                                         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]);
8658                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8659                                         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]);
8660                         }
8661                 }
8662                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8663                         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]);
8664                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8665                 {
8666                         // if this is opaque use alpha blend which will darken the earlier
8667                         // passes cheaply.
8668                         //
8669                         // if this is an alpha blended material, all the earlier passes
8670                         // were darkened by fog already, so we only need to add the fog
8671                         // color ontop through the fog mask texture
8672                         //
8673                         // if this is an additive blended material, all the earlier passes
8674                         // were darkened by fog already, and we should not add fog color
8675                         // (because the background was not darkened, there is no fog color
8676                         // that was lost behind it).
8677                         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]);
8678                 }
8679         }
8680
8681         return t->currentframe;
8682 }
8683
8684 rsurfacestate_t rsurface;
8685
8686 void R_Mesh_ResizeArrays(int newvertices)
8687 {
8688         float *base;
8689         if (rsurface.array_size >= newvertices)
8690                 return;
8691         if (rsurface.array_modelvertex3f)
8692                 Mem_Free(rsurface.array_modelvertex3f);
8693         rsurface.array_size = (newvertices + 1023) & ~1023;
8694         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
8695         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
8696         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
8697         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
8698         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
8699         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
8700         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
8701         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
8702         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
8703         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
8704         rsurface.array_color4f           = base + rsurface.array_size * 27;
8705         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
8706 }
8707
8708 void RSurf_ActiveWorldEntity(void)
8709 {
8710         dp_model_t *model = r_refdef.scene.worldmodel;
8711         //if (rsurface.entity == r_refdef.scene.worldentity)
8712         //      return;
8713         rsurface.entity = r_refdef.scene.worldentity;
8714         rsurface.skeleton = NULL;
8715         rsurface.ent_skinnum = 0;
8716         rsurface.ent_qwskin = -1;
8717         rsurface.ent_shadertime = 0;
8718         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8719         if (rsurface.array_size < model->surfmesh.num_vertices)
8720                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
8721         rsurface.matrix = identitymatrix;
8722         rsurface.inversematrix = identitymatrix;
8723         rsurface.matrixscale = 1;
8724         rsurface.inversematrixscale = 1;
8725         R_EntityMatrix(&identitymatrix);
8726         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8727         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8728         rsurface.fograngerecip = r_refdef.fograngerecip;
8729         rsurface.fogheightfade = r_refdef.fogheightfade;
8730         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8731         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8732         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8733         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8734         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8735         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8736         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8737         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8738         rsurface.colormod[3] = 1;
8739         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);
8740         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8741         rsurface.frameblend[0].lerp = 1;
8742         rsurface.ent_alttextures = false;
8743         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8744         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8745         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8746         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
8747         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8748         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8749         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
8750         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8751         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8752         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
8753         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8754         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8755         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
8756         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8757         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8758         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
8759         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8760         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8761         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
8762         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8763         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8764         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
8765         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8766         rsurface.modelelement3i = model->surfmesh.data_element3i;
8767         rsurface.modelelement3s = model->surfmesh.data_element3s;
8768         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
8769         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
8770         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8771         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
8772         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
8773         rsurface.modelsurfaces = model->data_surfaces;
8774         rsurface.generatedvertex = false;
8775         rsurface.vertex3f  = rsurface.modelvertex3f;
8776         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
8777         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8778         rsurface.svector3f = rsurface.modelsvector3f;
8779         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
8780         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8781         rsurface.tvector3f = rsurface.modeltvector3f;
8782         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
8783         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8784         rsurface.normal3f  = rsurface.modelnormal3f;
8785         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
8786         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8787         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
8788 }
8789
8790 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8791 {
8792         dp_model_t *model = ent->model;
8793         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8794         //      return;
8795         rsurface.entity = (entity_render_t *)ent;
8796         rsurface.skeleton = ent->skeleton;
8797         rsurface.ent_skinnum = ent->skinnum;
8798         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;
8799         rsurface.ent_shadertime = ent->shadertime;
8800         rsurface.ent_flags = ent->flags;
8801         if (rsurface.array_size < model->surfmesh.num_vertices)
8802                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
8803         rsurface.matrix = ent->matrix;
8804         rsurface.inversematrix = ent->inversematrix;
8805         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8806         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8807         R_EntityMatrix(&rsurface.matrix);
8808         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8809         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8810         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8811         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8812         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8813         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8814         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8815         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8816         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8817         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8818         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8819         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8820         rsurface.colormod[3] = ent->alpha;
8821         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8822         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8823         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8824         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8825         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8826         if (ent->model->brush.submodel && !prepass)
8827         {
8828                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8829                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8830         }
8831         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
8832         {
8833                 if (ent->animcache_vertex3f && !r_framedata_failed)
8834                 {
8835                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8836                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8837                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8838                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8839                 }
8840                 else if (wanttangents)
8841                 {
8842                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
8843                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
8844                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
8845                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
8846                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
8847                 }
8848                 else if (wantnormals)
8849                 {
8850                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
8851                         rsurface.modelsvector3f = NULL;
8852                         rsurface.modeltvector3f = NULL;
8853                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
8854                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
8855                 }
8856                 else
8857                 {
8858                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
8859                         rsurface.modelsvector3f = NULL;
8860                         rsurface.modeltvector3f = NULL;
8861                         rsurface.modelnormal3f = NULL;
8862                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
8863                 }
8864                 rsurface.modelvertex3f_bufferobject = 0;
8865                 rsurface.modelvertex3f_bufferoffset = 0;
8866                 rsurface.modelsvector3f_bufferobject = 0;
8867                 rsurface.modelsvector3f_bufferoffset = 0;
8868                 rsurface.modeltvector3f_bufferobject = 0;
8869                 rsurface.modeltvector3f_bufferoffset = 0;
8870                 rsurface.modelnormal3f_bufferobject = 0;
8871                 rsurface.modelnormal3f_bufferoffset = 0;
8872                 rsurface.generatedvertex = true;
8873         }
8874         else
8875         {
8876                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8877                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
8878                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8879                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8880                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
8881                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8882                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8883                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
8884                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8885                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8886                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
8887                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8888                 rsurface.generatedvertex = false;
8889         }
8890         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8891         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
8892         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8893         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8894         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
8895         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8896         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8897         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
8898         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8899         rsurface.modelelement3i = model->surfmesh.data_element3i;
8900         rsurface.modelelement3s = model->surfmesh.data_element3s;
8901         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
8902         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
8903         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8904         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
8905         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
8906         rsurface.modelsurfaces = model->data_surfaces;
8907         rsurface.vertex3f  = rsurface.modelvertex3f;
8908         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
8909         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8910         rsurface.svector3f = rsurface.modelsvector3f;
8911         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
8912         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8913         rsurface.tvector3f = rsurface.modeltvector3f;
8914         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
8915         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8916         rsurface.normal3f  = rsurface.modelnormal3f;
8917         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
8918         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8919         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
8920 }
8921
8922 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)
8923 {
8924         rsurface.entity = r_refdef.scene.worldentity;
8925         rsurface.skeleton = NULL;
8926         rsurface.ent_skinnum = 0;
8927         rsurface.ent_qwskin = -1;
8928         rsurface.ent_shadertime = shadertime;
8929         rsurface.ent_flags = entflags;
8930         rsurface.modelnum_vertices = numvertices;
8931         rsurface.modelnum_triangles = numtriangles;
8932         if (rsurface.array_size < rsurface.modelnum_vertices)
8933                 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
8934         rsurface.matrix = *matrix;
8935         rsurface.inversematrix = *inversematrix;
8936         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8937         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8938         R_EntityMatrix(&rsurface.matrix);
8939         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8940         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8941         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8942         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8943         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8944         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8945         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8946         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8947         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8948         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8949         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8950         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8951         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);
8952         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8953         rsurface.frameblend[0].lerp = 1;
8954         rsurface.ent_alttextures = false;
8955         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8956         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8957         if (wanttangents)
8958         {
8959                 rsurface.modelvertex3f = vertex3f;
8960                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
8961                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
8962                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
8963         }
8964         else if (wantnormals)
8965         {
8966                 rsurface.modelvertex3f = vertex3f;
8967                 rsurface.modelsvector3f = NULL;
8968                 rsurface.modeltvector3f = NULL;
8969                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
8970         }
8971         else
8972         {
8973                 rsurface.modelvertex3f = vertex3f;
8974                 rsurface.modelsvector3f = NULL;
8975                 rsurface.modeltvector3f = NULL;
8976                 rsurface.modelnormal3f = NULL;
8977         }
8978         rsurface.modelvertex3f_bufferobject = 0;
8979         rsurface.modelvertex3f_bufferoffset = 0;
8980         rsurface.modelsvector3f_bufferobject = 0;
8981         rsurface.modelsvector3f_bufferoffset = 0;
8982         rsurface.modeltvector3f_bufferobject = 0;
8983         rsurface.modeltvector3f_bufferoffset = 0;
8984         rsurface.modelnormal3f_bufferobject = 0;
8985         rsurface.modelnormal3f_bufferoffset = 0;
8986         rsurface.generatedvertex = true;
8987         rsurface.modellightmapcolor4f  = color4f;
8988         rsurface.modellightmapcolor4f_bufferobject = 0;
8989         rsurface.modellightmapcolor4f_bufferoffset = 0;
8990         rsurface.modeltexcoordtexture2f  = texcoord2f;
8991         rsurface.modeltexcoordtexture2f_bufferobject = 0;
8992         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8993         rsurface.modeltexcoordlightmap2f  = NULL;
8994         rsurface.modeltexcoordlightmap2f_bufferobject = 0;
8995         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8996         rsurface.modelelement3i = element3i;
8997         rsurface.modelelement3s = element3s;
8998         rsurface.modelelement3i_bufferobject = 0;
8999         rsurface.modelelement3s_bufferobject = 0;
9000         rsurface.modellightmapoffsets = NULL;
9001         rsurface.modelsurfaces = NULL;
9002         rsurface.vertex3f  = rsurface.modelvertex3f;
9003         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9004         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9005         rsurface.svector3f = rsurface.modelsvector3f;
9006         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9007         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9008         rsurface.tvector3f = rsurface.modeltvector3f;
9009         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9010         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9011         rsurface.normal3f  = rsurface.modelnormal3f;
9012         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9013         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9014         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9015
9016         if (rsurface.modelnum_vertices && rsurface.modelelement3i)
9017         {
9018                 if ((wantnormals || wanttangents) && !normal3f)
9019                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9020                 if (wanttangents && !svector3f)
9021                         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);
9022         }
9023 }
9024
9025 float RSurf_FogPoint(const float *v)
9026 {
9027         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9028         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9029         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9030         float FogHeightFade = r_refdef.fogheightfade;
9031         float fogfrac;
9032         unsigned int fogmasktableindex;
9033         if (r_refdef.fogplaneviewabove)
9034                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9035         else
9036                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9037         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9038         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9039 }
9040
9041 float RSurf_FogVertex(const float *v)
9042 {
9043         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9044         float FogPlaneViewDist = rsurface.fogplaneviewdist;
9045         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9046         float FogHeightFade = rsurface.fogheightfade;
9047         float fogfrac;
9048         unsigned int fogmasktableindex;
9049         if (r_refdef.fogplaneviewabove)
9050                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9051         else
9052                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9053         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9054         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9055 }
9056
9057 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9058 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9059 {
9060         int deformindex;
9061         int texturesurfaceindex;
9062         int i, j;
9063         float amplitude;
9064         float animpos;
9065         float scale;
9066         const float *v1, *in_tc;
9067         float *out_tc;
9068         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9069         float waveparms[4];
9070         q3shaderinfo_deform_t *deform;
9071         // 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
9072         if (rsurface.generatedvertex)
9073         {
9074                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
9075                         generatenormals = true;
9076                 for (i = 0;i < Q3MAXDEFORMS;i++)
9077                 {
9078                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
9079                         {
9080                                 generatetangents = true;
9081                                 generatenormals = true;
9082                         }
9083                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
9084                                 generatenormals = true;
9085                 }
9086                 if (generatenormals && !rsurface.modelnormal3f)
9087                 {
9088                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9089                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
9090                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
9091                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9092                 }
9093                 if (generatetangents && !rsurface.modelsvector3f)
9094                 {
9095                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9096                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
9097                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
9098                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9099                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
9100                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
9101                         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);
9102                 }
9103         }
9104         rsurface.vertex3f  = rsurface.modelvertex3f;
9105         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9106         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9107         rsurface.svector3f = rsurface.modelsvector3f;
9108         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9109         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9110         rsurface.tvector3f = rsurface.modeltvector3f;
9111         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9112         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9113         rsurface.normal3f  = rsurface.modelnormal3f;
9114         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9115         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9116         // if vertices are deformed (sprite flares and things in maps, possibly
9117         // water waves, bulges and other deformations), generate them into
9118         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
9119         // (may be static model data or generated data for an animated model, or
9120         //  the previous deform pass)
9121         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
9122         {
9123                 switch (deform->deform)
9124                 {
9125                 default:
9126                 case Q3DEFORM_PROJECTIONSHADOW:
9127                 case Q3DEFORM_TEXT0:
9128                 case Q3DEFORM_TEXT1:
9129                 case Q3DEFORM_TEXT2:
9130                 case Q3DEFORM_TEXT3:
9131                 case Q3DEFORM_TEXT4:
9132                 case Q3DEFORM_TEXT5:
9133                 case Q3DEFORM_TEXT6:
9134                 case Q3DEFORM_TEXT7:
9135                 case Q3DEFORM_NONE:
9136                         break;
9137                 case Q3DEFORM_AUTOSPRITE:
9138                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9139                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9140                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9141                         VectorNormalize(newforward);
9142                         VectorNormalize(newright);
9143                         VectorNormalize(newup);
9144                         // make deformed versions of only the model vertices used by the specified surfaces
9145                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9146                         {
9147                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9148                                 // a single autosprite surface can contain multiple sprites...
9149                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9150                                 {
9151                                         VectorClear(center);
9152                                         for (i = 0;i < 4;i++)
9153                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9154                                         VectorScale(center, 0.25f, center);
9155                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
9156                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
9157                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
9158                                         for (i = 0;i < 4;i++)
9159                                         {
9160                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
9161                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9162                                         }
9163                                 }
9164                                 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);
9165                                 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);
9166                         }
9167                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9168                         rsurface.vertex3f_bufferobject = 0;
9169                         rsurface.vertex3f_bufferoffset = 0;
9170                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9171                         rsurface.svector3f_bufferobject = 0;
9172                         rsurface.svector3f_bufferoffset = 0;
9173                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9174                         rsurface.tvector3f_bufferobject = 0;
9175                         rsurface.tvector3f_bufferoffset = 0;
9176                         rsurface.normal3f = rsurface.array_deformednormal3f;
9177                         rsurface.normal3f_bufferobject = 0;
9178                         rsurface.normal3f_bufferoffset = 0;
9179                         break;
9180                 case Q3DEFORM_AUTOSPRITE2:
9181                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9182                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9183                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9184                         VectorNormalize(newforward);
9185                         VectorNormalize(newright);
9186                         VectorNormalize(newup);
9187                         // make deformed versions of only the model vertices used by the specified surfaces
9188                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9189                         {
9190                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9191                                 const float *v1, *v2;
9192                                 vec3_t start, end;
9193                                 float f, l;
9194                                 struct
9195                                 {
9196                                         float length2;
9197                                         const float *v1;
9198                                         const float *v2;
9199                                 }
9200                                 shortest[2];
9201                                 memset(shortest, 0, sizeof(shortest));
9202                                 // a single autosprite surface can contain multiple sprites...
9203                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9204                                 {
9205                                         VectorClear(center);
9206                                         for (i = 0;i < 4;i++)
9207                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9208                                         VectorScale(center, 0.25f, center);
9209                                         // find the two shortest edges, then use them to define the
9210                                         // axis vectors for rotating around the central axis
9211                                         for (i = 0;i < 6;i++)
9212                                         {
9213                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
9214                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
9215 #if 0
9216                                                 Debug_PolygonBegin(NULL, 0);
9217                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
9218                                                 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);
9219                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
9220                                                 Debug_PolygonEnd();
9221 #endif
9222                                                 l = VectorDistance2(v1, v2);
9223                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9224                                                 if (v1[2] != v2[2])
9225                                                         l += (1.0f / 1024.0f);
9226                                                 if (shortest[0].length2 > l || i == 0)
9227                                                 {
9228                                                         shortest[1] = shortest[0];
9229                                                         shortest[0].length2 = l;
9230                                                         shortest[0].v1 = v1;
9231                                                         shortest[0].v2 = v2;
9232                                                 }
9233                                                 else if (shortest[1].length2 > l || i == 1)
9234                                                 {
9235                                                         shortest[1].length2 = l;
9236                                                         shortest[1].v1 = v1;
9237                                                         shortest[1].v2 = v2;
9238                                                 }
9239                                         }
9240                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9241                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9242 #if 0
9243                                         Debug_PolygonBegin(NULL, 0);
9244                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
9245                                         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);
9246                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
9247                                         Debug_PolygonEnd();
9248 #endif
9249                                         // this calculates the right vector from the shortest edge
9250                                         // and the up vector from the edge midpoints
9251                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9252                                         VectorNormalize(right);
9253                                         VectorSubtract(end, start, up);
9254                                         VectorNormalize(up);
9255                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9256                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9257                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9258                                         VectorNegate(forward, forward);
9259                                         VectorReflect(forward, 0, up, forward);
9260                                         VectorNormalize(forward);
9261                                         CrossProduct(up, forward, newright);
9262                                         VectorNormalize(newright);
9263 #if 0
9264                                         Debug_PolygonBegin(NULL, 0);
9265                                         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);
9266                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
9267                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
9268                                         Debug_PolygonEnd();
9269 #endif
9270 #if 0
9271                                         Debug_PolygonBegin(NULL, 0);
9272                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
9273                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
9274                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
9275                                         Debug_PolygonEnd();
9276 #endif
9277                                         // rotate the quad around the up axis vector, this is made
9278                                         // especially easy by the fact we know the quad is flat,
9279                                         // so we only have to subtract the center position and
9280                                         // measure distance along the right vector, and then
9281                                         // multiply that by the newright vector and add back the
9282                                         // center position
9283                                         // we also need to subtract the old position to undo the
9284                                         // displacement from the center, which we do with a
9285                                         // DotProduct, the subtraction/addition of center is also
9286                                         // optimized into DotProducts here
9287                                         l = DotProduct(right, center);
9288                                         for (i = 0;i < 4;i++)
9289                                         {
9290                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
9291                                                 f = DotProduct(right, v1) - l;
9292                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9293                                         }
9294                                 }
9295                                 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);
9296                                 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);
9297                         }
9298                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9299                         rsurface.vertex3f_bufferobject = 0;
9300                         rsurface.vertex3f_bufferoffset = 0;
9301                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9302                         rsurface.svector3f_bufferobject = 0;
9303                         rsurface.svector3f_bufferoffset = 0;
9304                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9305                         rsurface.tvector3f_bufferobject = 0;
9306                         rsurface.tvector3f_bufferoffset = 0;
9307                         rsurface.normal3f = rsurface.array_deformednormal3f;
9308                         rsurface.normal3f_bufferobject = 0;
9309                         rsurface.normal3f_bufferoffset = 0;
9310                         break;
9311                 case Q3DEFORM_NORMAL:
9312                         // deform the normals to make reflections wavey
9313                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9314                         {
9315                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9316                                 for (j = 0;j < surface->num_vertices;j++)
9317                                 {
9318                                         float vertex[3];
9319                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
9320                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
9321                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
9322                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9323                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9324                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9325                                         VectorNormalize(normal);
9326                                 }
9327                                 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);
9328                         }
9329                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9330                         rsurface.svector3f_bufferobject = 0;
9331                         rsurface.svector3f_bufferoffset = 0;
9332                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9333                         rsurface.tvector3f_bufferobject = 0;
9334                         rsurface.tvector3f_bufferoffset = 0;
9335                         rsurface.normal3f = rsurface.array_deformednormal3f;
9336                         rsurface.normal3f_bufferobject = 0;
9337                         rsurface.normal3f_bufferoffset = 0;
9338                         break;
9339                 case Q3DEFORM_WAVE:
9340                         // deform vertex array to make wavey water and flags and such
9341                         waveparms[0] = deform->waveparms[0];
9342                         waveparms[1] = deform->waveparms[1];
9343                         waveparms[2] = deform->waveparms[2];
9344                         waveparms[3] = deform->waveparms[3];
9345                         // this is how a divisor of vertex influence on deformation
9346                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9347                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9348                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9349                         {
9350                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9351                                 for (j = 0;j < surface->num_vertices;j++)
9352                                 {
9353                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
9354                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9355                                         // if the wavefunc depends on time, evaluate it per-vertex
9356                                         if (waveparms[3])
9357                                         {
9358                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
9359                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9360                                         }
9361                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9362                                 }
9363                         }
9364                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9365                         rsurface.vertex3f_bufferobject = 0;
9366                         rsurface.vertex3f_bufferoffset = 0;
9367                         break;
9368                 case Q3DEFORM_BULGE:
9369                         // deform vertex array to make the surface have moving bulges
9370                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9371                         {
9372                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9373                                 for (j = 0;j < surface->num_vertices;j++)
9374                                 {
9375                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
9376                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9377                                 }
9378                         }
9379                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9380                         rsurface.vertex3f_bufferobject = 0;
9381                         rsurface.vertex3f_bufferoffset = 0;
9382                         break;
9383                 case Q3DEFORM_MOVE:
9384                         // deform vertex array
9385                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9386                         VectorScale(deform->parms, scale, waveparms);
9387                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9388                         {
9389                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9390                                 for (j = 0;j < surface->num_vertices;j++)
9391                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9392                         }
9393                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9394                         rsurface.vertex3f_bufferobject = 0;
9395                         rsurface.vertex3f_bufferoffset = 0;
9396                         break;
9397                 }
9398         }
9399         // generate texcoords based on the chosen texcoord source
9400         switch(rsurface.texture->tcgen.tcgen)
9401         {
9402         default:
9403         case Q3TCGEN_TEXTURE:
9404                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
9405                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
9406                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9407                 break;
9408         case Q3TCGEN_LIGHTMAP:
9409                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
9410                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
9411                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
9412                 break;
9413         case Q3TCGEN_VECTOR:
9414                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9415                 {
9416                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9417                         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)
9418                         {
9419                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
9420                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
9421                         }
9422                 }
9423                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9424                 rsurface.texcoordtexture2f_bufferobject  = 0;
9425                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9426                 break;
9427         case Q3TCGEN_ENVIRONMENT:
9428                 // make environment reflections using a spheremap
9429                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9430                 {
9431                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9432                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
9433                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
9434                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
9435                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
9436                         {
9437                                 // identical to Q3A's method, but executed in worldspace so
9438                                 // carried models can be shiny too
9439
9440                                 float viewer[3], d, reflected[3], worldreflected[3];
9441
9442                                 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
9443                                 // VectorNormalize(viewer);
9444
9445                                 d = DotProduct(normal, viewer);
9446
9447                                 reflected[0] = normal[0]*2*d - viewer[0];
9448                                 reflected[1] = normal[1]*2*d - viewer[1];
9449                                 reflected[2] = normal[2]*2*d - viewer[2];
9450                                 // note: this is proportinal to viewer, so we can normalize later
9451
9452                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9453                                 VectorNormalize(worldreflected);
9454
9455                                 // note: this sphere map only uses world x and z!
9456                                 // so positive and negative y will LOOK THE SAME.
9457                                 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
9458                                 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
9459                         }
9460                 }
9461                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9462                 rsurface.texcoordtexture2f_bufferobject  = 0;
9463                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9464                 break;
9465         }
9466         // the only tcmod that needs software vertex processing is turbulent, so
9467         // check for it here and apply the changes if needed
9468         // and we only support that as the first one
9469         // (handling a mixture of turbulent and other tcmods would be problematic
9470         //  without punting it entirely to a software path)
9471         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9472         {
9473                 amplitude = rsurface.texture->tcmods[0].parms[1];
9474                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
9475                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9476                 {
9477                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9478                         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)
9479                         {
9480                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9481                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9482                         }
9483                 }
9484                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9485                 rsurface.texcoordtexture2f_bufferobject  = 0;
9486                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9487         }
9488         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
9489         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
9490         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9491         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
9492 }
9493
9494 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9495 {
9496         int i, j;
9497         const msurface_t *surface = texturesurfacelist[0];
9498         const msurface_t *surface2;
9499         int firstvertex;
9500         int endvertex;
9501         int numvertices;
9502         int numtriangles;
9503         // TODO: lock all array ranges before render, rather than on each surface
9504         if (texturenumsurfaces == 1)
9505         {
9506                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9507                 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);
9508         }
9509         else if (r_batchmode.integer == 2)
9510         {
9511                 #define MAXBATCHTRIANGLES 4096
9512                 int batchtriangles = 0;
9513                 static int batchelements[MAXBATCHTRIANGLES*3];
9514                 for (i = 0;i < texturenumsurfaces;i = j)
9515                 {
9516                         surface = texturesurfacelist[i];
9517                         j = i + 1;
9518                         if (surface->num_triangles > MAXBATCHTRIANGLES)
9519                         {
9520                                 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);
9521                                 continue;
9522                         }
9523                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9524                         batchtriangles = surface->num_triangles;
9525                         firstvertex = surface->num_firstvertex;
9526                         endvertex = surface->num_firstvertex + surface->num_vertices;
9527                         for (;j < texturenumsurfaces;j++)
9528                         {
9529                                 surface2 = texturesurfacelist[j];
9530                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9531                                         break;
9532                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9533                                 batchtriangles += surface2->num_triangles;
9534                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
9535                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9536                         }
9537                         surface2 = texturesurfacelist[j-1];
9538                         numvertices = endvertex - firstvertex;
9539                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9540                 }
9541         }
9542         else if (r_batchmode.integer == 1)
9543         {
9544                 for (i = 0;i < texturenumsurfaces;i = j)
9545                 {
9546                         surface = texturesurfacelist[i];
9547                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9548                                 if (texturesurfacelist[j] != surface2)
9549                                         break;
9550                         surface2 = texturesurfacelist[j-1];
9551                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9552                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9553                         GL_LockArrays(surface->num_firstvertex, numvertices);
9554                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9555                 }
9556         }
9557         else
9558         {
9559                 for (i = 0;i < texturenumsurfaces;i++)
9560                 {
9561                         surface = texturesurfacelist[i];
9562                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9563                         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);
9564                 }
9565         }
9566 }
9567
9568 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
9569 {
9570         switch(vid.renderpath)
9571         {
9572         case RENDERPATH_CGGL:
9573 #ifdef SUPPORTCG
9574                 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
9575                 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
9576 #endif
9577                 break;
9578         case RENDERPATH_GL20:
9579                 if (r_glsl_permutation->loc_Texture_Lightmap  >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
9580                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
9581                 break;
9582         case RENDERPATH_GL13:
9583         case RENDERPATH_GL11:
9584                 R_Mesh_TexBind(0, surface->lightmaptexture);
9585                 break;
9586         }
9587 }
9588
9589 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
9590 {
9591         // pick the closest matching water plane and bind textures
9592         int planeindex, vertexindex;
9593         float d, bestd;
9594         vec3_t vert;
9595         const float *v;
9596         r_waterstate_waterplane_t *p, *bestp;
9597         bestd = 0;
9598         bestp = NULL;
9599         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9600         {
9601                 d = 0;
9602                 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
9603                 {
9604                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9605                         d += fabs(PlaneDiff(vert, &p->plane));
9606                 }
9607                 if (bestd > d || !bestp)
9608                 {
9609                         bestd = d;
9610                         bestp = p;
9611                 }
9612         }
9613         switch(vid.renderpath)
9614         {
9615         case RENDERPATH_CGGL:
9616 #ifdef SUPPORTCG
9617                 if (r_cg_permutation->fp_Texture_Refraction) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR
9618                 if (r_cg_permutation->fp_Texture_Reflection) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR
9619 #endif
9620                 break;
9621         case RENDERPATH_GL20:
9622                 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
9623                 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
9624                 break;
9625         case RENDERPATH_GL13:
9626         case RENDERPATH_GL11:
9627                 break;
9628         }
9629 }
9630
9631 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9632 {
9633         int i;
9634         const msurface_t *surface;
9635         if (r_waterstate.renderingscene)
9636                 return;
9637         for (i = 0;i < texturenumsurfaces;i++)
9638         {
9639                 surface = texturesurfacelist[i];
9640                 RSurf_BindLightmapForSurface(surface);
9641                 RSurf_BindReflectionForSurface(surface);
9642                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9643                 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);
9644         }
9645 }
9646
9647 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9648 {
9649         int i;
9650         int j;
9651         const msurface_t *surface = texturesurfacelist[0];
9652         const msurface_t *surface2;
9653         int firstvertex;
9654         int endvertex;
9655         int numvertices;
9656         int numtriangles;
9657         if (texturenumsurfaces == 1)
9658         {
9659                 RSurf_BindLightmapForSurface(surface);
9660                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9661                 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);
9662         }
9663         else if (r_batchmode.integer == 2)
9664         {
9665 #define MAXBATCHTRIANGLES 4096
9666                 int batchtriangles = 0;
9667                 static int batchelements[MAXBATCHTRIANGLES*3];
9668                 for (i = 0;i < texturenumsurfaces;i = j)
9669                 {
9670                         surface = texturesurfacelist[i];
9671                         RSurf_BindLightmapForSurface(surface);
9672                         j = i + 1;
9673                         if (surface->num_triangles > MAXBATCHTRIANGLES)
9674                         {
9675                                 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);
9676                                 continue;
9677                         }
9678                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9679                         batchtriangles = surface->num_triangles;
9680                         firstvertex = surface->num_firstvertex;
9681                         endvertex = surface->num_firstvertex + surface->num_vertices;
9682                         for (;j < texturenumsurfaces;j++)
9683                         {
9684                                 surface2 = texturesurfacelist[j];
9685                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9686                                         break;
9687                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9688                                 batchtriangles += surface2->num_triangles;
9689                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
9690                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9691                         }
9692                         surface2 = texturesurfacelist[j-1];
9693                         numvertices = endvertex - firstvertex;
9694                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9695                 }
9696         }
9697         else if (r_batchmode.integer == 1)
9698         {
9699 #if 0
9700                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
9701                 for (i = 0;i < texturenumsurfaces;i = j)
9702                 {
9703                         surface = texturesurfacelist[i];
9704                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9705                                 if (texturesurfacelist[j] != surface2)
9706                                         break;
9707                         Con_Printf(" %i", j - i);
9708                 }
9709                 Con_Printf("\n");
9710                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
9711 #endif
9712                 for (i = 0;i < texturenumsurfaces;i = j)
9713                 {
9714                         surface = texturesurfacelist[i];
9715                         RSurf_BindLightmapForSurface(surface);
9716                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9717                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
9718                                         break;
9719 #if 0
9720                         Con_Printf(" %i", j - i);
9721 #endif
9722                         surface2 = texturesurfacelist[j-1];
9723                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9724                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9725                         GL_LockArrays(surface->num_firstvertex, numvertices);
9726                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9727                 }
9728 #if 0
9729                 Con_Printf("\n");
9730 #endif
9731         }
9732         else
9733         {
9734                 for (i = 0;i < texturenumsurfaces;i++)
9735                 {
9736                         surface = texturesurfacelist[i];
9737                         RSurf_BindLightmapForSurface(surface);
9738                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9739                         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);
9740                 }
9741         }
9742 }
9743
9744 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9745 {
9746         int j;
9747         int texturesurfaceindex;
9748         if (r_showsurfaces.integer == 2)
9749         {
9750                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9751                 {
9752                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9753                         for (j = 0;j < surface->num_triangles;j++)
9754                         {
9755                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
9756                                 GL_Color(f, f, f, 1);
9757                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9758                         }
9759                 }
9760         }
9761         else
9762         {
9763                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9764                 {
9765                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9766                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
9767                         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);
9768                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9769                         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);
9770                 }
9771         }
9772 }
9773
9774 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9775 {
9776         int texturesurfaceindex;
9777         int i;
9778         const float *v;
9779         float *c2;
9780         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9781         {
9782                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9783                 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)
9784                 {
9785                         c2[0] = 0.5;
9786                         c2[1] = 0.5;
9787                         c2[2] = 0.5;
9788                         c2[3] = 1;
9789                 }
9790         }
9791         rsurface.lightmapcolor4f = rsurface.array_color4f;
9792         rsurface.lightmapcolor4f_bufferobject = 0;
9793         rsurface.lightmapcolor4f_bufferoffset = 0;
9794 }
9795
9796 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9797 {
9798         int texturesurfaceindex;
9799         int i;
9800         float f;
9801         const float *v;
9802         const float *c;
9803         float *c2;
9804         if (rsurface.lightmapcolor4f)
9805         {
9806                 // generate color arrays for the surfaces in this list
9807                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9808                 {
9809                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9810                         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)
9811                         {
9812                                 f = RSurf_FogVertex(v);
9813                                 c2[0] = c[0] * f;
9814                                 c2[1] = c[1] * f;
9815                                 c2[2] = c[2] * f;
9816                                 c2[3] = c[3];
9817                         }
9818                 }
9819         }
9820         else
9821         {
9822                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9823                 {
9824                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9825                         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)
9826                         {
9827                                 f = RSurf_FogVertex(v);
9828                                 c2[0] = f;
9829                                 c2[1] = f;
9830                                 c2[2] = f;
9831                                 c2[3] = 1;
9832                         }
9833                 }
9834         }
9835         rsurface.lightmapcolor4f = rsurface.array_color4f;
9836         rsurface.lightmapcolor4f_bufferobject = 0;
9837         rsurface.lightmapcolor4f_bufferoffset = 0;
9838 }
9839
9840 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9841 {
9842         int texturesurfaceindex;
9843         int i;
9844         float f;
9845         const float *v;
9846         const float *c;
9847         float *c2;
9848         if (!rsurface.lightmapcolor4f)
9849                 return;
9850         // generate color arrays for the surfaces in this list
9851         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9852         {
9853                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9854                 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)
9855                 {
9856                         f = RSurf_FogVertex(v);
9857                         c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9858                         c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9859                         c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9860                         c2[3] = c[3];
9861                 }
9862         }
9863         rsurface.lightmapcolor4f = rsurface.array_color4f;
9864         rsurface.lightmapcolor4f_bufferobject = 0;
9865         rsurface.lightmapcolor4f_bufferoffset = 0;
9866 }
9867
9868 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
9869 {
9870         int texturesurfaceindex;
9871         int i;
9872         const float *c;
9873         float *c2;
9874         if (!rsurface.lightmapcolor4f)
9875                 return;
9876         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9877         {
9878                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9879                 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)
9880                 {
9881                         c2[0] = c[0] * r;
9882                         c2[1] = c[1] * g;
9883                         c2[2] = c[2] * b;
9884                         c2[3] = c[3] * a;
9885                 }
9886         }
9887         rsurface.lightmapcolor4f = rsurface.array_color4f;
9888         rsurface.lightmapcolor4f_bufferobject = 0;
9889         rsurface.lightmapcolor4f_bufferoffset = 0;
9890 }
9891
9892 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9893 {
9894         int texturesurfaceindex;
9895         int i;
9896         const float *c;
9897         float *c2;
9898         if (!rsurface.lightmapcolor4f)
9899                 return;
9900         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9901         {
9902                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9903                 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)
9904                 {
9905                         c2[0] = c[0] + r_refdef.scene.ambient;
9906                         c2[1] = c[1] + r_refdef.scene.ambient;
9907                         c2[2] = c[2] + r_refdef.scene.ambient;
9908                         c2[3] = c[3];
9909                 }
9910         }
9911         rsurface.lightmapcolor4f = rsurface.array_color4f;
9912         rsurface.lightmapcolor4f_bufferobject = 0;
9913         rsurface.lightmapcolor4f_bufferoffset = 0;
9914 }
9915
9916 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9917 {
9918         // TODO: optimize
9919         rsurface.lightmapcolor4f = NULL;
9920         rsurface.lightmapcolor4f_bufferobject = 0;
9921         rsurface.lightmapcolor4f_bufferoffset = 0;
9922         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
9923         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
9924         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
9925         GL_Color(r, g, b, a);
9926         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
9927 }
9928
9929 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9930 {
9931         // TODO: optimize applyfog && applycolor case
9932         // just apply fog if necessary, and tint the fog color array if necessary
9933         rsurface.lightmapcolor4f = NULL;
9934         rsurface.lightmapcolor4f_bufferobject = 0;
9935         rsurface.lightmapcolor4f_bufferoffset = 0;
9936         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
9937         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
9938         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
9939         GL_Color(r, g, b, a);
9940         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9941 }
9942
9943 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9944 {
9945         int texturesurfaceindex;
9946         int i;
9947         float *c;
9948         // TODO: optimize
9949         if (texturesurfacelist[0]->lightmapinfo)
9950         {
9951                 // generate color arrays for the surfaces in this list
9952                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9953                 {
9954                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9955                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
9956                         {
9957                                 if (surface->lightmapinfo->samples)
9958                                 {
9959                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
9960                                         float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
9961                                         VectorScale(lm, scale, c);
9962                                         if (surface->lightmapinfo->styles[1] != 255)
9963                                         {
9964                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9965                                                 lm += size3;
9966                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
9967                                                 VectorMA(c, scale, lm, c);
9968                                                 if (surface->lightmapinfo->styles[2] != 255)
9969                                                 {
9970                                                         lm += size3;
9971                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
9972                                                         VectorMA(c, scale, lm, c);
9973                                                         if (surface->lightmapinfo->styles[3] != 255)
9974                                                         {
9975                                                                 lm += size3;
9976                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
9977                                                                 VectorMA(c, scale, lm, c);
9978                                                         }
9979                                                 }
9980                                         }
9981                                 }
9982                                 else
9983                                         VectorClear(c);
9984                                 c[3] = 1;
9985                         }
9986                 }
9987                 rsurface.lightmapcolor4f = rsurface.array_color4f;
9988                 rsurface.lightmapcolor4f_bufferobject = 0;
9989                 rsurface.lightmapcolor4f_bufferoffset = 0;
9990         }
9991         else
9992         {
9993                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
9994                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
9995                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
9996         }
9997         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
9998         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
9999         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10000         GL_Color(r, g, b, a);
10001         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10002 }
10003
10004 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
10005 {
10006         int texturesurfaceindex;
10007         int i;
10008         float f;
10009         float alpha;
10010         const float *v;
10011         const float *n;
10012         float *c;
10013         vec3_t ambientcolor;
10014         vec3_t diffusecolor;
10015         vec3_t lightdir;
10016         // TODO: optimize
10017         // model lighting
10018         VectorCopy(rsurface.modellight_lightdir, lightdir);
10019         f = 0.5f * r_refdef.lightmapintensity;
10020         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10021         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10022         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10023         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10024         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10025         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10026         alpha = *a;
10027         if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
10028         {
10029                 // generate color arrays for the surfaces in this list
10030                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10031                 {
10032                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10033                         int numverts = surface->num_vertices;
10034                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
10035                         n = rsurface.normal3f + 3 * surface->num_firstvertex;
10036                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
10037                         // q3-style directional shading
10038                         for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
10039                         {
10040                                 if ((f = DotProduct(n, lightdir)) > 0)
10041                                         VectorMA(ambientcolor, f, diffusecolor, c);
10042                                 else
10043                                         VectorCopy(ambientcolor, c);
10044                                 c[3] = alpha;
10045                         }
10046                 }
10047                 *r = 1;
10048                 *g = 1;
10049                 *b = 1;
10050                 *a = 1;
10051                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10052                 rsurface.lightmapcolor4f_bufferobject = 0;
10053                 rsurface.lightmapcolor4f_bufferoffset = 0;
10054                 *applycolor = false;
10055         }
10056         else
10057         {
10058                 *r = ambientcolor[0];
10059                 *g = ambientcolor[1];
10060                 *b = ambientcolor[2];
10061                 rsurface.lightmapcolor4f = NULL;
10062                 rsurface.lightmapcolor4f_bufferobject = 0;
10063                 rsurface.lightmapcolor4f_bufferoffset = 0;
10064         }
10065 }
10066
10067 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10068 {
10069         RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
10070         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10071         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10072         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10073         GL_Color(r, g, b, a);
10074         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10075 }
10076
10077 void RSurf_SetupDepthAndCulling(void)
10078 {
10079         // submodels are biased to avoid z-fighting with world surfaces that they
10080         // may be exactly overlapping (avoids z-fighting artifacts on certain
10081         // doors and things in Quake maps)
10082         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10083         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10084         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10085         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10086 }
10087
10088 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10089 {
10090         // transparent sky would be ridiculous
10091         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10092                 return;
10093         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10094         skyrenderlater = true;
10095         RSurf_SetupDepthAndCulling();
10096         GL_DepthMask(true);
10097         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10098         // skymasking on them, and Quake3 never did sky masking (unlike
10099         // software Quake and software Quake2), so disable the sky masking
10100         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10101         // and skymasking also looks very bad when noclipping outside the
10102         // level, so don't use it then either.
10103         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
10104         {
10105                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10106                 R_Mesh_ColorPointer(NULL, 0, 0);
10107                 R_Mesh_ResetTextureState();
10108                 if (skyrendermasked)
10109                 {
10110                         R_SetupShader_DepthOrShadow();
10111                         // depth-only (masking)
10112                         GL_ColorMask(0,0,0,0);
10113                         // just to make sure that braindead drivers don't draw
10114                         // anything despite that colormask...
10115                         GL_BlendFunc(GL_ZERO, GL_ONE);
10116                 }
10117                 else
10118                 {
10119                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10120                         // fog sky
10121                         GL_BlendFunc(GL_ONE, GL_ZERO);
10122                 }
10123                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10124                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10125                 if (skyrendermasked)
10126                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10127         }
10128         R_Mesh_ResetTextureState();
10129         GL_Color(1, 1, 1, 1);
10130 }
10131
10132 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10133 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10134 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10135 {
10136         qboolean reflect = (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)) && !prepass;
10137         qboolean refract = (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !prepass;
10138
10139         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
10140                 return;
10141
10142         if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
10143                 R_Mesh_ColorPointer(NULL, 0, 0);
10144         else
10145                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
10146
10147         if (refract)
10148         {
10149                 // render background
10150                 GL_BlendFunc(GL_ONE, GL_ZERO);
10151                 GL_DepthMask(true);
10152                 GL_AlphaTest(false);
10153
10154                 GL_Color(1, 1, 1, 1);
10155                 R_Mesh_ColorPointer(NULL, 0, 0);
10156
10157                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
10158                 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10159                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10160                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
10161                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
10162                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
10163                 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10164                 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10165                 GL_LockArrays(0, 0);
10166
10167                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
10168                 GL_DepthMask(false);
10169                 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
10170                         R_Mesh_ColorPointer(NULL, 0, 0);
10171                 else
10172                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
10173         }
10174
10175         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
10176
10177         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10178         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10179         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
10180         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
10181         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
10182         if (!prepass)
10183                 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10184
10185         if (refract)
10186         {
10187                 GL_BlendFunc(GL_ONE, GL_ZERO);
10188                 GL_DepthMask(true);
10189                 GL_AlphaTest(false);
10190         }
10191         else
10192         {
10193                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
10194                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10195                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0 && !r_shadow_usingdeferredprepass);
10196         }
10197
10198         if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10199         {
10200                 if (refract || reflect)
10201                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10202                 else
10203                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10204         }
10205         else
10206         {
10207                 if (refract || reflect)
10208                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10209                 else
10210                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10211         }
10212         GL_LockArrays(0, 0);
10213 }
10214
10215 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10216 {
10217         // OpenGL 1.3 path - anything not completely ancient
10218         int texturesurfaceindex;
10219         qboolean applycolor;
10220         qboolean applyfog;
10221         int layerindex;
10222         const texturelayer_t *layer;
10223         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10224
10225         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10226         {
10227                 vec4_t layercolor;
10228                 int layertexrgbscale;
10229                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10230                 {
10231                         if (layerindex == 0)
10232                                 GL_AlphaTest(true);
10233                         else
10234                         {
10235                                 GL_AlphaTest(false);
10236                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10237                         }
10238                 }
10239                 GL_DepthMask(layer->depthmask && writedepth);
10240                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10241                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10242                 {
10243                         layertexrgbscale = 4;
10244                         VectorScale(layer->color, 0.25f, layercolor);
10245                 }
10246                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10247                 {
10248                         layertexrgbscale = 2;
10249                         VectorScale(layer->color, 0.5f, layercolor);
10250                 }
10251                 else
10252                 {
10253                         layertexrgbscale = 1;
10254                         VectorScale(layer->color, 1.0f, layercolor);
10255                 }
10256                 layercolor[3] = layer->color[3];
10257                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10258                 R_Mesh_ColorPointer(NULL, 0, 0);
10259                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10260                 switch (layer->type)
10261                 {
10262                 case TEXTURELAYERTYPE_LITTEXTURE:
10263                         // single-pass lightmapped texture with 2x rgbscale
10264                         //R_Mesh_TexBind(0, r_texture_white);
10265                         R_Mesh_TexMatrix(0, NULL);
10266                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10267                         R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10268                         R_Mesh_TexBind(1, layer->texture);
10269                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10270                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10271                         R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10272                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10273                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10274                         else if (rsurface.uselightmaptexture)
10275                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10276                         else
10277                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10278                         break;
10279                 case TEXTURELAYERTYPE_TEXTURE:
10280                         // singletexture unlit texture with transparency support
10281                         R_Mesh_TexBind(0, layer->texture);
10282                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10283                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10284                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10285                         R_Mesh_TexBind(1, 0);
10286                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10287                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10288                         break;
10289                 case TEXTURELAYERTYPE_FOG:
10290                         // singletexture fogging
10291                         if (layer->texture)
10292                         {
10293                                 R_Mesh_TexBind(0, layer->texture);
10294                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10295                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10296                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10297                         }
10298                         else
10299                         {
10300                                 R_Mesh_TexBind(0, 0);
10301                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10302                         }
10303                         R_Mesh_TexBind(1, 0);
10304                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10305                         // generate a color array for the fog pass
10306                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10307                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10308                         {
10309                                 int i;
10310                                 float f;
10311                                 const float *v;
10312                                 float *c;
10313                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10314                                 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)
10315                                 {
10316                                         f = 1 - RSurf_FogVertex(v);
10317                                         c[0] = layercolor[0];
10318                                         c[1] = layercolor[1];
10319                                         c[2] = layercolor[2];
10320                                         c[3] = f * layercolor[3];
10321                                 }
10322                         }
10323                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10324                         break;
10325                 default:
10326                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10327                 }
10328                 GL_LockArrays(0, 0);
10329         }
10330         CHECKGLERROR
10331         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10332         {
10333                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10334                 GL_AlphaTest(false);
10335         }
10336 }
10337
10338 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10339 {
10340         // OpenGL 1.1 - crusty old voodoo path
10341         int texturesurfaceindex;
10342         qboolean applyfog;
10343         int layerindex;
10344         const texturelayer_t *layer;
10345         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10346
10347         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10348         {
10349                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10350                 {
10351                         if (layerindex == 0)
10352                                 GL_AlphaTest(true);
10353                         else
10354                         {
10355                                 GL_AlphaTest(false);
10356                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10357                         }
10358                 }
10359                 GL_DepthMask(layer->depthmask && writedepth);
10360                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10361                 R_Mesh_ColorPointer(NULL, 0, 0);
10362                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10363                 switch (layer->type)
10364                 {
10365                 case TEXTURELAYERTYPE_LITTEXTURE:
10366                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10367                         {
10368                                 // two-pass lit texture with 2x rgbscale
10369                                 // first the lightmap pass
10370                                 //R_Mesh_TexBind(0, r_texture_white);
10371                                 R_Mesh_TexMatrix(0, NULL);
10372                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10373                                 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10374                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10375                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10376                                 else if (rsurface.uselightmaptexture)
10377                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10378                                 else
10379                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10380                                 GL_LockArrays(0, 0);
10381                                 // then apply the texture to it
10382                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10383                                 R_Mesh_TexBind(0, layer->texture);
10384                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10385                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10386                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10387                                 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);
10388                         }
10389                         else
10390                         {
10391                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10392                                 R_Mesh_TexBind(0, layer->texture);
10393                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10394                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10395                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10396                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10397                                         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);
10398                                 else
10399                                         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);
10400                         }
10401                         break;
10402                 case TEXTURELAYERTYPE_TEXTURE:
10403                         // singletexture unlit texture with transparency support
10404                         R_Mesh_TexBind(0, layer->texture);
10405                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10406                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10407                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10408                         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);
10409                         break;
10410                 case TEXTURELAYERTYPE_FOG:
10411                         // singletexture fogging
10412                         if (layer->texture)
10413                         {
10414                                 R_Mesh_TexBind(0, layer->texture);
10415                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10416                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10417                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10418                         }
10419                         else
10420                         {
10421                                 R_Mesh_TexBind(0, 0);
10422                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10423                         }
10424                         // generate a color array for the fog pass
10425                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10426                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10427                         {
10428                                 int i;
10429                                 float f;
10430                                 const float *v;
10431                                 float *c;
10432                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10433                                 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)
10434                                 {
10435                                         f = 1 - RSurf_FogVertex(v);
10436                                         c[0] = layer->color[0];
10437                                         c[1] = layer->color[1];
10438                                         c[2] = layer->color[2];
10439                                         c[3] = f * layer->color[3];
10440                                 }
10441                         }
10442                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10443                         break;
10444                 default:
10445                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10446                 }
10447                 GL_LockArrays(0, 0);
10448         }
10449         CHECKGLERROR
10450         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10451         {
10452                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10453                 GL_AlphaTest(false);
10454         }
10455 }
10456
10457 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10458 {
10459         float c[4];
10460
10461         GL_AlphaTest(false);
10462         R_Mesh_ColorPointer(NULL, 0, 0);
10463         R_Mesh_ResetTextureState();
10464         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10465
10466         if(rsurface.texture && rsurface.texture->currentskinframe)
10467         {
10468                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10469                 c[3] *= rsurface.texture->currentalpha;
10470         }
10471         else
10472         {
10473                 c[0] = 1;
10474                 c[1] = 0;
10475                 c[2] = 1;
10476                 c[3] = 1;
10477         }
10478
10479         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10480         {
10481                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10482                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10483                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10484         }
10485
10486         // brighten it up (as texture value 127 means "unlit")
10487         c[0] *= 2 * r_refdef.view.colorscale;
10488         c[1] *= 2 * r_refdef.view.colorscale;
10489         c[2] *= 2 * r_refdef.view.colorscale;
10490
10491         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10492                 c[3] *= r_wateralpha.value;
10493
10494         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10495         {
10496                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10497                 GL_DepthMask(false);
10498         }
10499         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10500         {
10501                 GL_BlendFunc(GL_ONE, GL_ONE);
10502                 GL_DepthMask(false);
10503         }
10504         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10505         {
10506                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10507                 GL_DepthMask(false);
10508         }
10509         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10510         {
10511                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10512                 GL_DepthMask(false);
10513         }
10514         else
10515         {
10516                 GL_BlendFunc(GL_ONE, GL_ZERO);
10517                 GL_DepthMask(writedepth);
10518         }
10519
10520         rsurface.lightmapcolor4f = NULL;
10521
10522         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10523         {
10524                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10525
10526                 rsurface.lightmapcolor4f = NULL;
10527                 rsurface.lightmapcolor4f_bufferobject = 0;
10528                 rsurface.lightmapcolor4f_bufferoffset = 0;
10529         }
10530         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10531         {
10532                 qboolean applycolor = true;
10533                 float one = 1.0;
10534
10535                 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10536
10537                 r_refdef.lightmapintensity = 1;
10538                 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
10539                 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10540         }
10541         else
10542         {
10543                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10544
10545                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10546                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10547                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10548         }
10549
10550         if(!rsurface.lightmapcolor4f)
10551                 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
10552
10553         RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
10554         RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
10555         if(r_refdef.fogenabled)
10556                 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
10557
10558         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10559         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10560 }
10561
10562 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10563 {
10564         CHECKGLERROR
10565         RSurf_SetupDepthAndCulling();
10566         if (r_showsurfaces.integer == 3 && !prepass)
10567         {
10568                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10569                 return;
10570         }
10571         switch (vid.renderpath)
10572         {
10573         case RENDERPATH_GL20:
10574         case RENDERPATH_CGGL:
10575                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10576                 break;
10577         case RENDERPATH_GL13:
10578                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10579                 break;
10580         case RENDERPATH_GL11:
10581                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10582                 break;
10583         }
10584         CHECKGLERROR
10585 }
10586
10587 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10588 {
10589         CHECKGLERROR
10590         RSurf_SetupDepthAndCulling();
10591         if (r_showsurfaces.integer == 3 && !prepass)
10592         {
10593                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10594                 return;
10595         }
10596         switch (vid.renderpath)
10597         {
10598         case RENDERPATH_GL20:
10599         case RENDERPATH_CGGL:
10600                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10601                 break;
10602         case RENDERPATH_GL13:
10603                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10604                 break;
10605         case RENDERPATH_GL11:
10606                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10607                 break;
10608         }
10609         CHECKGLERROR
10610 }
10611
10612 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10613 {
10614         int i, j;
10615         int texturenumsurfaces, endsurface;
10616         texture_t *texture;
10617         const msurface_t *surface;
10618         const msurface_t *texturesurfacelist[256];
10619
10620         // if the model is static it doesn't matter what value we give for
10621         // wantnormals and wanttangents, so this logic uses only rules applicable
10622         // to a model, knowing that they are meaningless otherwise
10623         if (ent == r_refdef.scene.worldentity)
10624                 RSurf_ActiveWorldEntity();
10625         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10626                 RSurf_ActiveModelEntity(ent, false, false, false);
10627         else
10628         {
10629                 switch (vid.renderpath)
10630                 {
10631                 case RENDERPATH_GL20:
10632                 case RENDERPATH_CGGL:
10633                         RSurf_ActiveModelEntity(ent, true, true, false);
10634                         break;
10635                 case RENDERPATH_GL13:
10636                 case RENDERPATH_GL11:
10637                         RSurf_ActiveModelEntity(ent, true, false, false);
10638                         break;
10639                 }
10640         }
10641
10642         if (r_transparentdepthmasking.integer)
10643         {
10644                 qboolean setup = false;
10645                 for (i = 0;i < numsurfaces;i = j)
10646                 {
10647                         j = i + 1;
10648                         surface = rsurface.modelsurfaces + surfacelist[i];
10649                         texture = surface->texture;
10650                         rsurface.texture = R_GetCurrentTexture(texture);
10651                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10652                         // scan ahead until we find a different texture
10653                         endsurface = min(i + 1024, numsurfaces);
10654                         texturenumsurfaces = 0;
10655                         texturesurfacelist[texturenumsurfaces++] = surface;
10656                         for (;j < endsurface;j++)
10657                         {
10658                                 surface = rsurface.modelsurfaces + surfacelist[j];
10659                                 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10660                                         break;
10661                                 texturesurfacelist[texturenumsurfaces++] = surface;
10662                         }
10663                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10664                                 continue;
10665                         // render the range of surfaces as depth
10666                         if (!setup)
10667                         {
10668                                 setup = true;
10669                                 GL_ColorMask(0,0,0,0);
10670                                 GL_Color(1,1,1,1);
10671                                 GL_DepthTest(true);
10672                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10673                                 GL_DepthMask(true);
10674                                 GL_AlphaTest(false);
10675                                 R_Mesh_ColorPointer(NULL, 0, 0);
10676                                 R_Mesh_ResetTextureState();
10677                                 R_SetupShader_DepthOrShadow();
10678                         }
10679                         RSurf_SetupDepthAndCulling();
10680                         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10681                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10682                 }
10683                 if (setup)
10684                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10685         }
10686
10687         for (i = 0;i < numsurfaces;i = j)
10688         {
10689                 j = i + 1;
10690                 surface = rsurface.modelsurfaces + surfacelist[i];
10691                 texture = surface->texture;
10692                 rsurface.texture = R_GetCurrentTexture(texture);
10693                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10694                 // scan ahead until we find a different texture
10695                 endsurface = min(i + 1024, numsurfaces);
10696                 texturenumsurfaces = 0;
10697                 texturesurfacelist[texturenumsurfaces++] = surface;
10698                 for (;j < endsurface;j++)
10699                 {
10700                         surface = rsurface.modelsurfaces + surfacelist[j];
10701                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10702                                 break;
10703                         texturesurfacelist[texturenumsurfaces++] = surface;
10704                 }
10705                 // render the range of surfaces
10706                 if (ent == r_refdef.scene.worldentity)
10707                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10708                 else
10709                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10710         }
10711         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10712         GL_AlphaTest(false);
10713 }
10714
10715 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10716 {
10717         // transparent surfaces get pushed off into the transparent queue
10718         int surfacelistindex;
10719         const msurface_t *surface;
10720         vec3_t tempcenter, center;
10721         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10722         {
10723                 surface = texturesurfacelist[surfacelistindex];
10724                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10725                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10726                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10727                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10728                 if (queueentity->transparent_offset) // transparent offset
10729                 {
10730                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10731                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10732                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10733                 }
10734                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10735         }
10736 }
10737
10738 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10739 {
10740         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10741         CHECKGLERROR
10742         if (depthonly)
10743         {
10744                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10745                         return;
10746                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10747                         return;
10748                 RSurf_SetupDepthAndCulling();
10749                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10750                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10751         }
10752         else if (prepass)
10753         {
10754                 if (!rsurface.texture->currentnumlayers)
10755                         return;
10756                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10757                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10758                 else
10759                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10760         }
10761         else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
10762         {
10763                 RSurf_SetupDepthAndCulling();
10764                 GL_AlphaTest(false);
10765                 R_Mesh_ColorPointer(NULL, 0, 0);
10766                 R_Mesh_ResetTextureState();
10767                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10768                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10769                 GL_DepthMask(true);
10770                 GL_BlendFunc(GL_ONE, GL_ZERO);
10771                 GL_Color(0, 0, 0, 1);
10772                 GL_DepthTest(writedepth);
10773                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10774         }
10775         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
10776         {
10777                 RSurf_SetupDepthAndCulling();
10778                 GL_AlphaTest(false);
10779                 R_Mesh_ColorPointer(NULL, 0, 0);
10780                 R_Mesh_ResetTextureState();
10781                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10782                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10783                 GL_DepthMask(true);
10784                 GL_BlendFunc(GL_ONE, GL_ZERO);
10785                 GL_DepthTest(true);
10786                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
10787         }
10788         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
10789                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10790         else if (!rsurface.texture->currentnumlayers)
10791                 return;
10792         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10793         {
10794                 // in the deferred case, transparent surfaces were queued during prepass
10795                 if (!r_shadow_usingdeferredprepass)
10796                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10797         }
10798         else
10799         {
10800                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10801                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10802         }
10803         CHECKGLERROR
10804 }
10805
10806 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10807 {
10808         int i, j;
10809         texture_t *texture;
10810         // break the surface list down into batches by texture and use of lightmapping
10811         for (i = 0;i < numsurfaces;i = j)
10812         {
10813                 j = i + 1;
10814                 // texture is the base texture pointer, rsurface.texture is the
10815                 // current frame/skin the texture is directing us to use (for example
10816                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10817                 // use skin 1 instead)
10818                 texture = surfacelist[i]->texture;
10819                 rsurface.texture = R_GetCurrentTexture(texture);
10820                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
10821                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10822                 {
10823                         // if this texture is not the kind we want, skip ahead to the next one
10824                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10825                                 ;
10826                         continue;
10827                 }
10828                 // simply scan ahead until we find a different texture or lightmap state
10829                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
10830                         ;
10831                 // render the range of surfaces
10832                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10833         }
10834 }
10835
10836 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10837 {
10838         CHECKGLERROR
10839         if (depthonly)
10840         {
10841                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10842                         return;
10843                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10844                         return;
10845                 RSurf_SetupDepthAndCulling();
10846                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10847                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10848         }
10849         else if (prepass)
10850         {
10851                 if (!rsurface.texture->currentnumlayers)
10852                         return;
10853                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10854                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10855                 else
10856                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10857         }
10858         else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
10859         {
10860                 RSurf_SetupDepthAndCulling();
10861                 GL_AlphaTest(false);
10862                 R_Mesh_ColorPointer(NULL, 0, 0);
10863                 R_Mesh_ResetTextureState();
10864                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10865                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10866                 GL_DepthMask(true);
10867                 GL_BlendFunc(GL_ONE, GL_ZERO);
10868                 GL_Color(0, 0, 0, 1);
10869                 GL_DepthTest(writedepth);
10870                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10871         }
10872         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10873         {
10874                 RSurf_SetupDepthAndCulling();
10875                 GL_AlphaTest(false);
10876                 R_Mesh_ColorPointer(NULL, 0, 0);
10877                 R_Mesh_ResetTextureState();
10878                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10879                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10880                 GL_DepthMask(true);
10881                 GL_BlendFunc(GL_ONE, GL_ZERO);
10882                 GL_DepthTest(true);
10883                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
10884         }
10885         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
10886                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10887         else if (!rsurface.texture->currentnumlayers)
10888                 return;
10889         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10890         {
10891                 // in the deferred case, transparent surfaces were queued during prepass
10892                 if (!r_shadow_usingdeferredprepass)
10893                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10894         }
10895         else
10896         {
10897                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10898                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10899         }
10900         CHECKGLERROR
10901 }
10902
10903 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10904 {
10905         int i, j;
10906         texture_t *texture;
10907         // break the surface list down into batches by texture and use of lightmapping
10908         for (i = 0;i < numsurfaces;i = j)
10909         {
10910                 j = i + 1;
10911                 // texture is the base texture pointer, rsurface.texture is the
10912                 // current frame/skin the texture is directing us to use (for example
10913                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10914                 // use skin 1 instead)
10915                 texture = surfacelist[i]->texture;
10916                 rsurface.texture = R_GetCurrentTexture(texture);
10917                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
10918                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10919                 {
10920                         // if this texture is not the kind we want, skip ahead to the next one
10921                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10922                                 ;
10923                         continue;
10924                 }
10925                 // simply scan ahead until we find a different texture or lightmap state
10926                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
10927                         ;
10928                 // render the range of surfaces
10929                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10930         }
10931 }
10932
10933 float locboxvertex3f[6*4*3] =
10934 {
10935         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10936         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10937         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10938         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10939         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10940         1,0,0, 0,0,0, 0,1,0, 1,1,0
10941 };
10942
10943 unsigned short locboxelements[6*2*3] =
10944 {
10945          0, 1, 2, 0, 2, 3,
10946          4, 5, 6, 4, 6, 7,
10947          8, 9,10, 8,10,11,
10948         12,13,14, 12,14,15,
10949         16,17,18, 16,18,19,
10950         20,21,22, 20,22,23
10951 };
10952
10953 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10954 {
10955         int i, j;
10956         cl_locnode_t *loc = (cl_locnode_t *)ent;
10957         vec3_t mins, size;
10958         float vertex3f[6*4*3];
10959         CHECKGLERROR
10960         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10961         GL_DepthMask(false);
10962         GL_DepthRange(0, 1);
10963         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10964         GL_DepthTest(true);
10965         GL_CullFace(GL_NONE);
10966         R_EntityMatrix(&identitymatrix);
10967
10968         R_Mesh_VertexPointer(vertex3f, 0, 0);
10969         R_Mesh_ColorPointer(NULL, 0, 0);
10970         R_Mesh_ResetTextureState();
10971         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10972
10973         i = surfacelist[0];
10974         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10975                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10976                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10977                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10978
10979         if (VectorCompare(loc->mins, loc->maxs))
10980         {
10981                 VectorSet(size, 2, 2, 2);
10982                 VectorMA(loc->mins, -0.5f, size, mins);
10983         }
10984         else
10985         {
10986                 VectorCopy(loc->mins, mins);
10987                 VectorSubtract(loc->maxs, loc->mins, size);
10988         }
10989
10990         for (i = 0;i < 6*4*3;)
10991                 for (j = 0;j < 3;j++, i++)
10992                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10993
10994         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
10995 }
10996
10997 void R_DrawLocs(void)
10998 {
10999         int index;
11000         cl_locnode_t *loc, *nearestloc;
11001         vec3_t center;
11002         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11003         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11004         {
11005                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11006                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11007         }
11008 }
11009
11010 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11011 {
11012         if (decalsystem->decals)
11013                 Mem_Free(decalsystem->decals);
11014         memset(decalsystem, 0, sizeof(*decalsystem));
11015 }
11016
11017 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)
11018 {
11019         tridecal_t *decal;
11020         tridecal_t *decals;
11021         int i;
11022         int maxdecals;
11023
11024         // expand or initialize the system
11025         if (decalsystem->maxdecals <= decalsystem->numdecals)
11026         {
11027                 decalsystem_t old = *decalsystem;
11028                 qboolean useshortelements;
11029                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11030                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11031                 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)));
11032                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11033                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11034                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11035                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11036                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11037                 if (decalsystem->numdecals)
11038                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11039                 if (old.decals)
11040                         Mem_Free(old.decals);
11041                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11042                         decalsystem->element3i[i] = i;
11043                 if (useshortelements)
11044                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11045                                 decalsystem->element3s[i] = i;
11046         }
11047
11048         // grab a decal and search for another free slot for the next one
11049         maxdecals = decalsystem->maxdecals;
11050         decals = decalsystem->decals;
11051         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11052         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
11053                 ;
11054         decalsystem->freedecal = i;
11055         if (decalsystem->numdecals <= i)
11056                 decalsystem->numdecals = i + 1;
11057
11058         // initialize the decal
11059         decal->lived = 0;
11060         decal->triangleindex = triangleindex;
11061         decal->surfaceindex = surfaceindex;
11062         decal->decalsequence = decalsequence;
11063         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
11064         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
11065         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
11066         decal->color4ub[0][3] = 255;
11067         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
11068         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
11069         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
11070         decal->color4ub[1][3] = 255;
11071         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
11072         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
11073         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
11074         decal->color4ub[2][3] = 255;
11075         decal->vertex3f[0][0] = v0[0];
11076         decal->vertex3f[0][1] = v0[1];
11077         decal->vertex3f[0][2] = v0[2];
11078         decal->vertex3f[1][0] = v1[0];
11079         decal->vertex3f[1][1] = v1[1];
11080         decal->vertex3f[1][2] = v1[2];
11081         decal->vertex3f[2][0] = v2[0];
11082         decal->vertex3f[2][1] = v2[1];
11083         decal->vertex3f[2][2] = v2[2];
11084         decal->texcoord2f[0][0] = t0[0];
11085         decal->texcoord2f[0][1] = t0[1];
11086         decal->texcoord2f[1][0] = t1[0];
11087         decal->texcoord2f[1][1] = t1[1];
11088         decal->texcoord2f[2][0] = t2[0];
11089         decal->texcoord2f[2][1] = t2[1];
11090 }
11091
11092 extern cvar_t cl_decals_bias;
11093 extern cvar_t cl_decals_models;
11094 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11095 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)
11096 {
11097         matrix4x4_t projection;
11098         decalsystem_t *decalsystem;
11099         qboolean dynamic;
11100         dp_model_t *model;
11101         const float *vertex3f;
11102         const msurface_t *surface;
11103         const msurface_t *surfaces;
11104         const int *surfacelist;
11105         const texture_t *texture;
11106         int numvertices;
11107         int numtriangles;
11108         int numsurfacelist;
11109         int surfacelistindex;
11110         int surfaceindex;
11111         int triangleindex;
11112         int decalsurfaceindex;
11113         int cornerindex;
11114         int index;
11115         int numpoints;
11116         const int *e;
11117         float localorigin[3];
11118         float localnormal[3];
11119         float localmins[3];
11120         float localmaxs[3];
11121         float localsize;
11122         float ilocalsize;
11123         float v[9][3];
11124         float tc[9][2];
11125         float c[9][4];
11126         //float normal[3];
11127         float planes[6][4];
11128         float f;
11129         float points[2][9][3];
11130         float angles[3];
11131         float temp[3];
11132
11133         decalsystem = &ent->decalsystem;
11134         model = ent->model;
11135         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11136         {
11137                 R_DecalSystem_Reset(&ent->decalsystem);
11138                 return;
11139         }
11140
11141         if (!model->brush.data_nodes && !cl_decals_models.integer)
11142         {
11143                 if (decalsystem->model)
11144                         R_DecalSystem_Reset(decalsystem);
11145                 return;
11146         }
11147
11148         if (decalsystem->model != model)
11149                 R_DecalSystem_Reset(decalsystem);
11150         decalsystem->model = model;
11151
11152         RSurf_ActiveModelEntity(ent, false, false, false);
11153
11154         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11155         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11156         VectorNormalize(localnormal);
11157         localsize = worldsize*rsurface.inversematrixscale;
11158         ilocalsize = 1.0f / localsize;
11159         localmins[0] = localorigin[0] - localsize;
11160         localmins[1] = localorigin[1] - localsize;
11161         localmins[2] = localorigin[2] - localsize;
11162         localmaxs[0] = localorigin[0] + localsize;
11163         localmaxs[1] = localorigin[1] + localsize;
11164         localmaxs[2] = localorigin[2] + localsize;
11165
11166         //VectorCopy(localnormal, planes[4]);
11167         //VectorVectors(planes[4], planes[2], planes[0]);
11168         AnglesFromVectors(angles, localnormal, NULL, false);
11169         AngleVectors(angles, planes[0], planes[2], planes[4]);
11170         VectorNegate(planes[0], planes[1]);
11171         VectorNegate(planes[2], planes[3]);
11172         VectorNegate(planes[4], planes[5]);
11173         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11174         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11175         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11176         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11177         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11178         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11179
11180 #if 1
11181 // works
11182 {
11183         matrix4x4_t forwardprojection;
11184         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11185         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11186 }
11187 #else
11188 // broken
11189 {
11190         float projectionvector[4][3];
11191         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11192         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11193         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11194         projectionvector[0][0] = planes[0][0] * ilocalsize;
11195         projectionvector[0][1] = planes[1][0] * ilocalsize;
11196         projectionvector[0][2] = planes[2][0] * ilocalsize;
11197         projectionvector[1][0] = planes[0][1] * ilocalsize;
11198         projectionvector[1][1] = planes[1][1] * ilocalsize;
11199         projectionvector[1][2] = planes[2][1] * ilocalsize;
11200         projectionvector[2][0] = planes[0][2] * ilocalsize;
11201         projectionvector[2][1] = planes[1][2] * ilocalsize;
11202         projectionvector[2][2] = planes[2][2] * ilocalsize;
11203         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11204         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11205         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11206         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11207 }
11208 #endif
11209
11210         dynamic = model->surfmesh.isanimated;
11211         vertex3f = rsurface.modelvertex3f;
11212         numsurfacelist = model->nummodelsurfaces;
11213         surfacelist = model->sortedmodelsurfaces;
11214         surfaces = model->data_surfaces;
11215         for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11216         {
11217                 surfaceindex = surfacelist[surfacelistindex];
11218                 surface = surfaces + surfaceindex;
11219                 // skip transparent surfaces
11220                 texture = surface->texture;
11221                 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11222                         continue;
11223                 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11224                         continue;
11225                 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11226                         continue;
11227                 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
11228                 numvertices = surface->num_vertices;
11229                 numtriangles = surface->num_triangles;
11230                 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
11231                 {
11232                         for (cornerindex = 0;cornerindex < 3;cornerindex++)
11233                         {
11234                                 index = 3*e[cornerindex];
11235                                 VectorCopy(vertex3f + index, v[cornerindex]);
11236                         }
11237                         // cull backfaces
11238                         //TriangleNormal(v[0], v[1], v[2], normal);
11239                         //if (DotProduct(normal, localnormal) < 0.0f)
11240                         //      continue;
11241                         // clip by each of the box planes formed from the projection matrix
11242                         // if anything survives, we emit the decal
11243                         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]);
11244                         if (numpoints < 3)
11245                                 continue;
11246                         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]);
11247                         if (numpoints < 3)
11248                                 continue;
11249                         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]);
11250                         if (numpoints < 3)
11251                                 continue;
11252                         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]);
11253                         if (numpoints < 3)
11254                                 continue;
11255                         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]);
11256                         if (numpoints < 3)
11257                                 continue;
11258                         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]);
11259                         if (numpoints < 3)
11260                                 continue;
11261                         // some part of the triangle survived, so we have to accept it...
11262                         if (dynamic)
11263                         {
11264                                 // dynamic always uses the original triangle
11265                                 numpoints = 3;
11266                                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11267                                 {
11268                                         index = 3*e[cornerindex];
11269                                         VectorCopy(vertex3f + index, v[cornerindex]);
11270                                 }
11271                         }
11272                         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11273                         {
11274                                 // convert vertex positions to texcoords
11275                                 Matrix4x4_Transform(&projection, v[cornerindex], temp);
11276                                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11277                                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11278                                 // calculate distance fade from the projection origin
11279                                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11280                                 f = bound(0.0f, f, 1.0f);
11281                                 c[cornerindex][0] = r * f;
11282                                 c[cornerindex][1] = g * f;
11283                                 c[cornerindex][2] = b * f;
11284                                 c[cornerindex][3] = 1.0f;
11285                                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11286                         }
11287                         if (dynamic)
11288                                 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);
11289                         else
11290                                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11291                                         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);
11292                 }
11293         }
11294 }
11295
11296 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11297 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)
11298 {
11299         int renderentityindex;
11300         float worldmins[3];
11301         float worldmaxs[3];
11302         entity_render_t *ent;
11303
11304         if (!cl_decals_newsystem.integer)
11305                 return;
11306
11307         worldmins[0] = worldorigin[0] - worldsize;
11308         worldmins[1] = worldorigin[1] - worldsize;
11309         worldmins[2] = worldorigin[2] - worldsize;
11310         worldmaxs[0] = worldorigin[0] + worldsize;
11311         worldmaxs[1] = worldorigin[1] + worldsize;
11312         worldmaxs[2] = worldorigin[2] + worldsize;
11313
11314         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11315
11316         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11317         {
11318                 ent = r_refdef.scene.entities[renderentityindex];
11319                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11320                         continue;
11321
11322                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11323         }
11324 }
11325
11326 typedef struct r_decalsystem_splatqueue_s
11327 {
11328         vec3_t worldorigin;
11329         vec3_t worldnormal;
11330         float color[4];
11331         float tcrange[4];
11332         float worldsize;
11333         int decalsequence;
11334 }
11335 r_decalsystem_splatqueue_t;
11336
11337 int r_decalsystem_numqueued = 0;
11338 #define MAX_DECALSYSTEM_QUEUE 1024
11339 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11340
11341 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)
11342 {
11343         r_decalsystem_splatqueue_t *queue;
11344
11345         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11346                 return;
11347
11348         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11349         VectorCopy(worldorigin, queue->worldorigin);
11350         VectorCopy(worldnormal, queue->worldnormal);
11351         Vector4Set(queue->color, r, g, b, a);
11352         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11353         queue->worldsize = worldsize;
11354         queue->decalsequence = cl.decalsequence++;
11355 }
11356
11357 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11358 {
11359         int i;
11360         r_decalsystem_splatqueue_t *queue;
11361
11362         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11363                 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);
11364         r_decalsystem_numqueued = 0;
11365 }
11366
11367 extern cvar_t cl_decals_max;
11368 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11369 {
11370         int i;
11371         decalsystem_t *decalsystem = &ent->decalsystem;
11372         int numdecals;
11373         int killsequence;
11374         tridecal_t *decal;
11375         float frametime;
11376         float lifetime;
11377
11378         if (!decalsystem->numdecals)
11379                 return;
11380
11381         if (r_showsurfaces.integer)
11382                 return;
11383
11384         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11385         {
11386                 R_DecalSystem_Reset(decalsystem);
11387                 return;
11388         }
11389
11390         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11391         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11392
11393         if (decalsystem->lastupdatetime)
11394                 frametime = (cl.time - decalsystem->lastupdatetime);
11395         else
11396                 frametime = 0;
11397         decalsystem->lastupdatetime = cl.time;
11398         decal = decalsystem->decals;
11399         numdecals = decalsystem->numdecals;
11400
11401         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11402         {
11403                 if (decal->color4ub[0][3])
11404                 {
11405                         decal->lived += frametime;
11406                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11407                         {
11408                                 memset(decal, 0, sizeof(*decal));
11409                                 if (decalsystem->freedecal > i)
11410                                         decalsystem->freedecal = i;
11411                         }
11412                 }
11413         }
11414         decal = decalsystem->decals;
11415         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
11416                 numdecals--;
11417
11418         // collapse the array by shuffling the tail decals into the gaps
11419         for (;;)
11420         {
11421                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
11422                         decalsystem->freedecal++;
11423                 if (decalsystem->freedecal == numdecals)
11424                         break;
11425                 decal[decalsystem->freedecal] = decal[--numdecals];
11426         }
11427
11428         decalsystem->numdecals = numdecals;
11429
11430         if (numdecals <= 0)
11431         {
11432                 // if there are no decals left, reset decalsystem
11433                 R_DecalSystem_Reset(decalsystem);
11434         }
11435 }
11436
11437 extern skinframe_t *decalskinframe;
11438 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11439 {
11440         int i;
11441         decalsystem_t *decalsystem = &ent->decalsystem;
11442         int numdecals;
11443         tridecal_t *decal;
11444         float fadedelay;
11445         float faderate;
11446         float alpha;
11447         float *v3f;
11448         float *c4f;
11449         float *t2f;
11450         const int *e;
11451         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11452         int numtris = 0;
11453
11454         numdecals = decalsystem->numdecals;
11455         if (!numdecals)
11456                 return;
11457
11458         if (r_showsurfaces.integer)
11459                 return;
11460
11461         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11462         {
11463                 R_DecalSystem_Reset(decalsystem);
11464                 return;
11465         }
11466
11467         // if the model is static it doesn't matter what value we give for
11468         // wantnormals and wanttangents, so this logic uses only rules applicable
11469         // to a model, knowing that they are meaningless otherwise
11470         if (ent == r_refdef.scene.worldentity)
11471                 RSurf_ActiveWorldEntity();
11472         else
11473                 RSurf_ActiveModelEntity(ent, false, false, false);
11474
11475         decalsystem->lastupdatetime = cl.time;
11476         decal = decalsystem->decals;
11477
11478         fadedelay = cl_decals_time.value;
11479         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11480
11481         // update vertex positions for animated models
11482         v3f = decalsystem->vertex3f;
11483         c4f = decalsystem->color4f;
11484         t2f = decalsystem->texcoord2f;
11485         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11486         {
11487                 if (!decal->color4ub[0][3])
11488                         continue;
11489
11490                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11491                         continue;
11492
11493                 // update color values for fading decals
11494                 if (decal->lived >= cl_decals_time.value)
11495                 {
11496                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11497                         alpha *= (1.0f/255.0f);
11498                 }
11499                 else
11500                         alpha = 1.0f/255.0f;
11501
11502                 c4f[ 0] = decal->color4ub[0][0] * alpha;
11503                 c4f[ 1] = decal->color4ub[0][1] * alpha;
11504                 c4f[ 2] = decal->color4ub[0][2] * alpha;
11505                 c4f[ 3] = 1;
11506                 c4f[ 4] = decal->color4ub[1][0] * alpha;
11507                 c4f[ 5] = decal->color4ub[1][1] * alpha;
11508                 c4f[ 6] = decal->color4ub[1][2] * alpha;
11509                 c4f[ 7] = 1;
11510                 c4f[ 8] = decal->color4ub[2][0] * alpha;
11511                 c4f[ 9] = decal->color4ub[2][1] * alpha;
11512                 c4f[10] = decal->color4ub[2][2] * alpha;
11513                 c4f[11] = 1;
11514
11515                 t2f[0] = decal->texcoord2f[0][0];
11516                 t2f[1] = decal->texcoord2f[0][1];
11517                 t2f[2] = decal->texcoord2f[1][0];
11518                 t2f[3] = decal->texcoord2f[1][1];
11519                 t2f[4] = decal->texcoord2f[2][0];
11520                 t2f[5] = decal->texcoord2f[2][1];
11521
11522                 // update vertex positions for animated models
11523                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
11524                 {
11525                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11526                         VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
11527                         VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
11528                         VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
11529                 }
11530                 else
11531                 {
11532                         VectorCopy(decal->vertex3f[0], v3f);
11533                         VectorCopy(decal->vertex3f[1], v3f + 3);
11534                         VectorCopy(decal->vertex3f[2], v3f + 6);
11535                 }
11536
11537                 v3f += 9;
11538                 c4f += 12;
11539                 t2f += 6;
11540                 numtris++;
11541         }
11542
11543         if (numtris > 0)
11544         {
11545                 r_refdef.stats.drawndecals += numtris;
11546
11547                 if (r_refdef.fogenabled)
11548                 {
11549                         switch(vid.renderpath)
11550                         {
11551                         case RENDERPATH_GL20:
11552                         case RENDERPATH_CGGL:
11553                         case RENDERPATH_GL13:
11554                         case RENDERPATH_GL11:
11555                                 for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
11556                                 {
11557                                         alpha = RSurf_FogVertex(v3f);
11558                                         c4f[0] *= alpha;
11559                                         c4f[1] *= alpha;
11560                                         c4f[2] *= alpha;
11561                                 }
11562                                 break;
11563                         }
11564                 }
11565
11566                 // now render the decals all at once
11567                 // (this assumes they all use one particle font texture!)
11568                 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);
11569                 R_Mesh_ResetTextureState();
11570                 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
11571                 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
11572                 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
11573                 GL_DepthMask(false);
11574                 GL_DepthRange(0, 1);
11575                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11576                 GL_DepthTest(true);
11577                 GL_CullFace(GL_NONE);
11578                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11579                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
11580                 GL_LockArrays(0, numtris * 3);
11581                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
11582                 GL_LockArrays(0, 0);
11583         }
11584 }
11585
11586 static void R_DrawModelDecals(void)
11587 {
11588         int i, numdecals;
11589
11590         // fade faster when there are too many decals
11591         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11592         for (i = 0;i < r_refdef.scene.numentities;i++)
11593                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11594
11595         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11596         for (i = 0;i < r_refdef.scene.numentities;i++)
11597                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11598                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11599
11600         R_DecalSystem_ApplySplatEntitiesQueue();
11601
11602         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11603         for (i = 0;i < r_refdef.scene.numentities;i++)
11604                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11605
11606         r_refdef.stats.totaldecals += numdecals;
11607
11608         if (r_showsurfaces.integer)
11609                 return;
11610
11611         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11612
11613         for (i = 0;i < r_refdef.scene.numentities;i++)
11614         {
11615                 if (!r_refdef.viewcache.entityvisible[i])
11616                         continue;
11617                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11618                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11619         }
11620 }
11621
11622 void R_DrawDebugModel(void)
11623 {
11624         entity_render_t *ent = rsurface.entity;
11625         int i, j, k, l, flagsmask;
11626         const int *elements;
11627         q3mbrush_t *brush;
11628         const msurface_t *surface;
11629         dp_model_t *model = ent->model;
11630         vec3_t v;
11631
11632         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11633
11634         R_Mesh_ColorPointer(NULL, 0, 0);
11635         R_Mesh_ResetTextureState();
11636         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11637         GL_DepthRange(0, 1);
11638         GL_DepthTest(!r_showdisabledepthtest.integer);
11639         GL_DepthMask(false);
11640         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11641
11642         if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
11643         {
11644                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11645                 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
11646                 {
11647                         if (brush->colbrushf && brush->colbrushf->numtriangles)
11648                         {
11649                                 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
11650                                 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);
11651                                 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
11652                         }
11653                 }
11654                 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
11655                 {
11656                         if (surface->num_collisiontriangles)
11657                         {
11658                                 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
11659                                 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);
11660                                 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
11661                         }
11662                 }
11663         }
11664
11665         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11666
11667         if (r_showtris.integer || r_shownormals.integer)
11668         {
11669                 if (r_showdisabledepthtest.integer)
11670                 {
11671                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11672                         GL_DepthMask(false);
11673                 }
11674                 else
11675                 {
11676                         GL_BlendFunc(GL_ONE, GL_ZERO);
11677                         GL_DepthMask(true);
11678                 }
11679                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11680                 {
11681                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11682                                 continue;
11683                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11684                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11685                         {
11686                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
11687                                 if (r_showtris.value > 0)
11688                                 {
11689                                         if (!rsurface.texture->currentlayers->depthmask)
11690                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11691                                         else if (ent == r_refdef.scene.worldentity)
11692                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11693                                         else
11694                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11695                                         elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
11696                                         R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
11697                                         R_Mesh_ColorPointer(NULL, 0, 0);
11698                                         R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
11699                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11700                                         //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
11701                                         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);
11702                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11703                                         CHECKGLERROR
11704                                 }
11705                                 if (r_shownormals.value < 0)
11706                                 {
11707                                         qglBegin(GL_LINES);
11708                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11709                                         {
11710                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11711                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11712                                                 qglVertex3f(v[0], v[1], v[2]);
11713                                                 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
11714                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11715                                                 qglVertex3f(v[0], v[1], v[2]);
11716                                         }
11717                                         qglEnd();
11718                                         CHECKGLERROR
11719                                 }
11720                                 if (r_shownormals.value > 0)
11721                                 {
11722                                         qglBegin(GL_LINES);
11723                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11724                                         {
11725                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11726                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11727                                                 qglVertex3f(v[0], v[1], v[2]);
11728                                                 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
11729                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11730                                                 qglVertex3f(v[0], v[1], v[2]);
11731                                         }
11732                                         qglEnd();
11733                                         CHECKGLERROR
11734                                         qglBegin(GL_LINES);
11735                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11736                                         {
11737                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11738                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11739                                                 qglVertex3f(v[0], v[1], v[2]);
11740                                                 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
11741                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11742                                                 qglVertex3f(v[0], v[1], v[2]);
11743                                         }
11744                                         qglEnd();
11745                                         CHECKGLERROR
11746                                         qglBegin(GL_LINES);
11747                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11748                                         {
11749                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11750                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11751                                                 qglVertex3f(v[0], v[1], v[2]);
11752                                                 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
11753                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11754                                                 qglVertex3f(v[0], v[1], v[2]);
11755                                         }
11756                                         qglEnd();
11757                                         CHECKGLERROR
11758                                 }
11759                         }
11760                 }
11761                 rsurface.texture = NULL;
11762         }
11763 }
11764
11765 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11766 int r_maxsurfacelist = 0;
11767 const msurface_t **r_surfacelist = NULL;
11768 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11769 {
11770         int i, j, endj, f, flagsmask;
11771         texture_t *t;
11772         dp_model_t *model = r_refdef.scene.worldmodel;
11773         msurface_t *surfaces;
11774         unsigned char *update;
11775         int numsurfacelist = 0;
11776         if (model == NULL)
11777                 return;
11778
11779         if (r_maxsurfacelist < model->num_surfaces)
11780         {
11781                 r_maxsurfacelist = model->num_surfaces;
11782                 if (r_surfacelist)
11783                         Mem_Free((msurface_t**)r_surfacelist);
11784                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11785         }
11786
11787         RSurf_ActiveWorldEntity();
11788
11789         surfaces = model->data_surfaces;
11790         update = model->brushq1.lightmapupdateflags;
11791
11792         // update light styles on this submodel
11793         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11794         {
11795                 model_brush_lightstyleinfo_t *style;
11796                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11797                 {
11798                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11799                         {
11800                                 int *list = style->surfacelist;
11801                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11802                                 for (j = 0;j < style->numsurfaces;j++)
11803                                         update[list[j]] = true;
11804                         }
11805                 }
11806         }
11807
11808         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11809
11810         if (debug)
11811         {
11812                 R_DrawDebugModel();
11813                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11814                 return;
11815         }
11816
11817         f = 0;
11818         t = NULL;
11819         rsurface.uselightmaptexture = false;
11820         rsurface.texture = NULL;
11821         rsurface.rtlight = NULL;
11822         numsurfacelist = 0;
11823         // add visible surfaces to draw list
11824         for (i = 0;i < model->nummodelsurfaces;i++)
11825         {
11826                 j = model->sortedmodelsurfaces[i];
11827                 if (r_refdef.viewcache.world_surfacevisible[j])
11828                         r_surfacelist[numsurfacelist++] = surfaces + j;
11829         }
11830         // update lightmaps if needed
11831         if (update)
11832         {
11833                 int updated = 0;
11834                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11835                 {
11836                         if (r_refdef.viewcache.world_surfacevisible[j])
11837                         {
11838                                 if (update[j])
11839                                 {
11840                                         updated++;
11841                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11842                                 }
11843                         }
11844                 }
11845         }
11846         // don't do anything if there were no surfaces
11847         if (!numsurfacelist)
11848         {
11849                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11850                 return;
11851         }
11852         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11853         GL_AlphaTest(false);
11854
11855         // add to stats if desired
11856         if (r_speeds.integer && !skysurfaces && !depthonly)
11857         {
11858                 r_refdef.stats.world_surfaces += numsurfacelist;
11859                 for (j = 0;j < numsurfacelist;j++)
11860                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11861         }
11862
11863         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11864 }
11865
11866 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11867 {
11868         int i, j, endj, f, flagsmask;
11869         texture_t *t;
11870         dp_model_t *model = ent->model;
11871         msurface_t *surfaces;
11872         unsigned char *update;
11873         int numsurfacelist = 0;
11874         if (model == NULL)
11875                 return;
11876
11877         if (r_maxsurfacelist < model->num_surfaces)
11878         {
11879                 r_maxsurfacelist = model->num_surfaces;
11880                 if (r_surfacelist)
11881                         Mem_Free((msurface_t **)r_surfacelist);
11882                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11883         }
11884
11885         // if the model is static it doesn't matter what value we give for
11886         // wantnormals and wanttangents, so this logic uses only rules applicable
11887         // to a model, knowing that they are meaningless otherwise
11888         if (ent == r_refdef.scene.worldentity)
11889                 RSurf_ActiveWorldEntity();
11890         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11891                 RSurf_ActiveModelEntity(ent, false, false, false);
11892         else if (prepass)
11893                 RSurf_ActiveModelEntity(ent, true, true, true);
11894         else if (depthonly)
11895                 RSurf_ActiveModelEntity(ent, false, false, false);
11896         else
11897         {
11898                 switch (vid.renderpath)
11899                 {
11900                 case RENDERPATH_GL20:
11901                 case RENDERPATH_CGGL:
11902                         RSurf_ActiveModelEntity(ent, true, true, false);
11903                         break;
11904                 case RENDERPATH_GL13:
11905                 case RENDERPATH_GL11:
11906                         RSurf_ActiveModelEntity(ent, true, false, false);
11907                         break;
11908                 }
11909         }
11910
11911         surfaces = model->data_surfaces;
11912         update = model->brushq1.lightmapupdateflags;
11913
11914         // update light styles
11915         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11916         {
11917                 model_brush_lightstyleinfo_t *style;
11918                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11919                 {
11920                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11921                         {
11922                                 int *list = style->surfacelist;
11923                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11924                                 for (j = 0;j < style->numsurfaces;j++)
11925                                         update[list[j]] = true;
11926                         }
11927                 }
11928         }
11929
11930         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11931
11932         if (debug)
11933         {
11934                 R_DrawDebugModel();
11935                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11936                 return;
11937         }
11938
11939         f = 0;
11940         t = NULL;
11941         rsurface.uselightmaptexture = false;
11942         rsurface.texture = NULL;
11943         rsurface.rtlight = NULL;
11944         numsurfacelist = 0;
11945         // add visible surfaces to draw list
11946         for (i = 0;i < model->nummodelsurfaces;i++)
11947                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11948         // don't do anything if there were no surfaces
11949         if (!numsurfacelist)
11950         {
11951                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11952                 return;
11953         }
11954         // update lightmaps if needed
11955         if (update)
11956         {
11957                 int updated = 0;
11958                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11959                 {
11960                         if (update[j])
11961                         {
11962                                 updated++;
11963                                 R_BuildLightMap(ent, surfaces + j);
11964                         }
11965                 }
11966         }
11967         if (update)
11968                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11969                         if (update[j])
11970                                 R_BuildLightMap(ent, surfaces + j);
11971         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11972         GL_AlphaTest(false);
11973
11974         // add to stats if desired
11975         if (r_speeds.integer && !skysurfaces && !depthonly)
11976         {
11977                 r_refdef.stats.entities_surfaces += numsurfacelist;
11978                 for (j = 0;j < numsurfacelist;j++)
11979                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11980         }
11981
11982         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11983 }
11984
11985 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11986 {
11987         static texture_t texture;
11988         static msurface_t surface;
11989         const msurface_t *surfacelist = &surface;
11990
11991         // fake enough texture and surface state to render this geometry
11992
11993         texture.update_lastrenderframe = -1; // regenerate this texture
11994         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11995         texture.currentskinframe = skinframe;
11996         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11997         texture.specularscalemod = 1;
11998         texture.specularpowermod = 1;
11999
12000         surface.texture = &texture;
12001         surface.num_triangles = numtriangles;
12002         surface.num_firsttriangle = firsttriangle;
12003         surface.num_vertices = numvertices;
12004         surface.num_firstvertex = firstvertex;
12005
12006         // now render it
12007         rsurface.texture = R_GetCurrentTexture(surface.texture);
12008         rsurface.uselightmaptexture = false;
12009         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12010 }
12011
12012 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)
12013 {
12014         static msurface_t surface;
12015         const msurface_t *surfacelist = &surface;
12016
12017         // fake enough texture and surface state to render this geometry
12018
12019         surface.texture = texture;
12020         surface.num_triangles = numtriangles;
12021         surface.num_firsttriangle = firsttriangle;
12022         surface.num_vertices = numvertices;
12023         surface.num_firstvertex = firstvertex;
12024
12025         // now render it
12026         rsurface.texture = R_GetCurrentTexture(surface.texture);
12027         rsurface.uselightmaptexture = false;
12028         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12029 }